<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>Vue 基础 | Justic</title><meta name="keywords" content="Vue"><meta name="author" content="Justic"><meta name="copyright" content="Justic"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="一、Vue知识点串讲1、基本使用下面，先来看一段最简单的代码，如下所示： &lt;!DOCTYPE html&gt;&lt;html lang&#x3D;&quot;en&quot;&gt;  &lt;head&gt;    &lt;meta charset&#x3D;&quot;UTF-8&quot; &#x2F;&gt;    &lt;meta name&#x3D;&quot;viewport&quot; content&#x3D;&amp;quot">
<meta property="og:type" content="article">
<meta property="og:title" content="Vue 基础">
<meta property="og:url" content="http://example.com/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/index.html">
<meta property="og:site_name" content="Justic">
<meta property="og:description" content="一、Vue知识点串讲1、基本使用下面，先来看一段最简单的代码，如下所示： &lt;!DOCTYPE html&gt;&lt;html lang&#x3D;&quot;en&quot;&gt;  &lt;head&gt;    &lt;meta charset&#x3D;&quot;UTF-8&quot; &#x2F;&gt;    &lt;meta name&#x3D;&quot;viewport&quot; content&#x3D;&amp;quot">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/yj/wallhaven-yj1kgl.jpg">
<meta property="article:published_time" content="2022-07-13T12:05:37.000Z">
<meta property="article:modified_time" content="2022-07-20T12:54:43.160Z">
<meta property="article:author" content="Justic">
<meta property="article:tag" content="Vue">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/yj/wallhaven-yj1kgl.jpg"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://example.com/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: {"path":"/search.xml","preload":false,"languages":{"hits_empty":"找不到您查询的内容：${query}"}},
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isAnchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'Vue 基础',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2022-07-20 20:54:43'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><!-- hexo injector head_end start --><link rel="stylesheet" href="https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu/lib/clock.min.css" /><!-- hexo injector head_end end --><meta name="generator" content="Hexo 6.2.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src= "" data-lazy-src="https://portrait.gitee.com/uploads/avatars/user/2982/8948190_JIAXInT_1624177607.png!avatar200" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">22</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">2</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">3</div></a></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fa fa-graduation-cap"></i><span> 博文</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/categories/"><i class="fa-fw fa fa-archive"></i><span> 分类</span></a></li><li><a class="site-page child" href="/tags/"><i class="fa-fw fa fa-tags"></i><span> 标签</span></a></li><li><a class="site-page child" href="/archives/"><i class="fa-fw fa fa-folder-open"></i><span> 归档</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/project/"><i class="fa-fw fas fa-images"></i><span> 项目</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fa fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/messageboard/"><i class="fa-fw fa fa-paper-plane"></i><span> 留言板</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于笔者</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/yj/wallhaven-yj1kgl.jpg')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">Justic</a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fa fa-graduation-cap"></i><span> 博文</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/categories/"><i class="fa-fw fa fa-archive"></i><span> 分类</span></a></li><li><a class="site-page child" href="/tags/"><i class="fa-fw fa fa-tags"></i><span> 标签</span></a></li><li><a class="site-page child" href="/archives/"><i class="fa-fw fa fa-folder-open"></i><span> 归档</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/project/"><i class="fa-fw fas fa-images"></i><span> 项目</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fa fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/messageboard/"><i class="fa-fw fa fa-paper-plane"></i><span> 留言板</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于笔者</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">Vue 基础</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2022-07-13T12:05:37.000Z" title="发表于 2022-07-13 20:05:37">2022-07-13</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2022-07-20T12:54:43.160Z" title="更新于 2022-07-20 20:54:43">2022-07-20</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Vue/">Vue</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">40.5k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>176分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="Vue 基础"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span><span class="post-meta-separator">|</span><span class="post-meta-commentcount"><i class="far fa-comments fa-fw post-meta-icon"></i><span class="post-meta-label">评论数:</span><a href="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/#post-comment" itemprop="discussionUrl"><span class="valine-comment-count" data-xid="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/" itemprop="commentCount"><i class="fa-solid fa-spinner fa-spin"></i></span></a></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h1 id="一、Vue知识点串讲"><a href="#一、Vue知识点串讲" class="headerlink" title="一、Vue知识点串讲"></a>一、<code>Vue</code>知识点串讲</h1><h2 id="1、基本使用"><a href="#1、基本使用" class="headerlink" title="1、基本使用"></a>1、基本使用</h2><p>下面，先来看一段最简单的代码，如下所示：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;Vue基本使用&lt;/title&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &#123;&#123; msg &#125;&#125;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script src=&quot;vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      //创建vue实例</span><br><span class="line">      const app = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data() &#123;</span><br><span class="line">          return &#123;</span><br><span class="line">            msg: &quot;hello world&quot;,</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">      setTimeout(() =&gt; &#123;</span><br><span class="line">        app.msg = &quot;hello Vue&quot;;</span><br><span class="line">      &#125;, 1000);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中,创建了<code>vue</code>的实例，并且指定了数据，最终数据展示在<code>id</code> 为<code>app</code>的这个<code>div</code>中，并且在停顿了 1 秒中以后，通过<code>Vue</code>的实例来修改对应的<code>msg</code>数据。</p>
<p>通过上面的代码，我们能够够看到<code>Vue</code>的核心理念是数据驱动的理念，所谓的数据驱动的理念：当数据发生变化的时候，用户界面也会发生相应的变化，开发者并不需要手动的去修改<code>dom</code>.</p>
<p>简单的理解：就是<code>vue.js</code>帮我们封装了数据和<code>dom</code>对象操作的映射，我们只需要关心数据的逻辑处理，数据的变</p>
<p>化就能够自然的通知页面进行页面的重新渲染。</p>
<p>这样做给我们带来的好处就是，我们不需要在代码中去频繁的操作<code>dom</code>了，这样提高了开发的效率，同时也避免了在操作<code>Dom</code>的时候出现的错误。</p>
<p><code>Vue.js</code>的数据驱动是通过<code>MVVM</code>这种框架来实现的，<code>MVVM</code> 框架主要包含三部分：<code>Model</code>,<code>View</code>,<code>ViewMode</code></p>
<p><code>Model</code>:指的是数据部分，对应到前端就是<code>JavaScript</code>对象。</p>
<p><code>View</code>:指的就是视图部分</p>
<p><code>ViewModel</code>: 就是连接视图与数据的中间件(中间桥梁)</p>
<p>以上三部分对应到代码中的位置如下图所示：</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/1.png"></p>
<p>下面，我们再来看一张图来理解一下<code>MVVM</code>框架的作用：</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/2.png"></p>
<p>数据(<code>Model</code>)和视图(<code>View</code>)是不能直接通讯的，而是需要通过<code>ViewModel</code>来实现双方的通讯。当数据(<code>Model</code>)变化的时候，<code>ViewModel</code>能够监听到这种变化，并及时通知<code>View</code>视图做出修改。同样的，当页面有事件触发的时候，<code>ViewModel</code>也能够监听到事件，并通知数据(<code>Model</code>)进行响应。所以<code>ViewModel</code>就相当于一个观察者，监控着双方的动作，并及时通知对方进行相应的操作。</p>
<p>简单的理解就是：<code>MVVM</code> 实现了将业务(数据)与视图进行分离的功能。</p>
<p>在这里还需要注意的一点就是：</p>
<p><code>MVVM</code>框架的三要素：响应式，模板引擎，渲染</p>
<p>响应式：<code>vue</code>如何监听数据的变化？</p>
<p>模板：<code>Vue</code>的模板如何编写和解析？怎样将具体的值替换掉<code>&#123;&#123;msg&#125;&#125;</code>内容，这就是模板引擎的解析。</p>
<p>渲染：<code>Vue</code>如何将模板转换成<code>html</code>? 其实就是有虚拟<code>DOM</code> 向真实<code>DOM</code>的转换。</p>
<p>在后面，我们还会深入探讨这块内容，包括我们自己模拟实现一个数据驱动的框架。</p>
<h2 id="2、模板语法"><a href="#2、模板语法" class="headerlink" title="2、模板语法"></a>2、模板语法</h2><h3 id="2-1-属性绑定"><a href="#2-1-属性绑定" class="headerlink" title="2.1 属性绑定"></a>2.1 属性绑定</h3><p>属性的绑定，下面先来看一下关于对属性的绑定</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;h2 v-bind:title=&quot;msg&quot;&gt;</span><br><span class="line">        &#123;&#123;msg&#125;&#125;</span><br><span class="line">      &lt;/h2&gt;</span><br><span class="line">    &lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们通过<code>v-bind</code>的方式给<code>h2</code>绑定了一个<code>title</code>属性。</p>
<p>当然，上面的代码我们也可以使用如下的方式来进行简化</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h2</span> <span class="attr">:title</span>=<span class="string">&quot;msg&quot;</span>&gt;</span>&#123;&#123;msg&#125;&#125;<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>为了避免闪烁的问题，也就是最开始的时候，出现:<code>&#123;&#123;msg&#125;&#125;</code>的情况，可以使用如下的绑定方式。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;h2 :title=&quot;msg&quot;&gt;</span><br><span class="line">        &lt;!-- &#123;&#123;msg&#125;&#125; --&gt;</span><br><span class="line">        &lt;span v-text=&quot;msg&quot;&gt;&lt;/span&gt;</span><br><span class="line">      &lt;/h2&gt;</span><br><span class="line">    &lt;/div&gt;</span><br></pre></td></tr></table></figure>

<h2 id="3、-列表渲染"><a href="#3、-列表渲染" class="headerlink" title="3、 列表渲染"></a>3、 列表渲染</h2><p>我们可以使用<code>v-for</code>指令基于一个数组来渲染一个列表.<code>v-for</code>指令需要使用<code>item in items</code>形式的语法。其中<code>items</code> 是源数组，而<code>item</code>则是被迭代的数组元素的别名。</p>
<p>基本实现的代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>列表渲染<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- users表示数组，item表示从数组中取出的对象,这个名字可以随意取 --&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 注意 v-for必须结合key属性来使用，它会唯一标识数组中的每一项，未来当数组中的那一项改变的时候，它会只更新那一项，好处就是提升性能。注意key的值唯一，不能重复 --&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- index表示数组的索引值，该名字可以随意定义 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">&quot;(item,index) in users&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span>&gt;</span></span><br><span class="line">          编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---索引:&#123;&#123;index&#125;&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: [</span></span><br><span class="line"><span class="language-javascript">            &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">id</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">            &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">id</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">            &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">id</span>: <span class="number">3</span>,</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">name</span>: <span class="string">&quot;老王&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          ],</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>注意：为了能够保证列表渲染的性能，我们需要给<code>v-for</code>添加<code>key</code>属性。<code>key</code>值必须唯一，而且不能使用<code>index</code>与<code>random</code>作为<code>key</code>的值。</p>
<p>关于这一点是与虚拟<code>DOM</code>算法密切相关的。在后面的课程中会最为一个重点来探讨虚拟<code>DOM</code>的内容。这也是面试的时候经常被问到的问题。</p>
<h2 id="4、v-model"><a href="#4、v-model" class="headerlink" title="4、v-model"></a>4、v-model</h2><p>在前面讲解<code>vue</code>简介的时候，我们说过，如果<code>model</code>中的数据发生了改变，会通过<code>ViewModel</code>通知<code>View</code>更新数据，这个效果前面我们也已经演示了，现在演示一下当<code>view</code>中的数据发生了变化后，怎样通过<code>ViewModel</code>来通知 model 来完成数据的更新。</p>
<p>其实这就是我们常说的，<strong>“双向数据绑定”</strong></p>
<p>怎样实现这种效果呢？可以通过 v-model 来实现。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!-- v-model指令用来双向数据绑定：就是model和view中的值进行同步变化 --&gt;</span><br><span class="line">&lt;!-- v-model只能在input/textarea/selet  也就是表单元素--&gt;</span><br></pre></td></tr></table></figure>

<p>具体代码实现如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;ie=edge&quot; /&gt;</span><br><span class="line">    &lt;title&gt;双向数据绑定&lt;/title&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line"></span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;input type=&quot;text&quot; v-model=&quot;userName&quot; /&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      const vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;</span><br><span class="line">          userName: &quot;zhangsan&quot;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>怎样验证 v-model 实现了双向数据绑定呢？</p>
<p>可以打开控制台，然后输入：<code>vm.userName</code> 发现输出的值为<code>&quot;zhangsan&quot;,</code> 取的是模型中的数据。</p>
<p>当在文本框中输入新的值后，在敲一下<code>vm.userName</code>发现对应的数据发生了变化，也就是视图中的数据发生了变化，模型中的数据也 会发生变化。</p>
<p>那么在控制台中直接给<code>vm.userName=&quot;lisi&quot;,</code>发现文本框中的值也发生了变化。</p>
<p>关于<code>v-model</code> 这个知识点，面试的时候经常会被问到的一个问题就是，自己能否模拟实现一个类似于<code>v-model</code>的双向数据绑定的效果。关于这个问题你可以先思考一下，在后面，我们会详细的讲解。</p>
<h2 id="5、v-on"><a href="#5、v-on" class="headerlink" title="5、v-on"></a>5、v-on</h2><p>怎样监听<code>dom</code>的事件呢？可以通过<code>v-on</code>指令完成，具体的代码如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;ie=edge&quot; /&gt;</span><br><span class="line">    &lt;title&gt;Document&lt;/title&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line"></span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;span&gt;&#123;&#123; name &#125;&#125;&lt;/span&gt;</span><br><span class="line">      &lt;!-- 通过v-on来指定对应的事件，然后后面跟上对应的方法名，方法的定义在methods完成 --&gt;</span><br><span class="line">      &lt;button v-on:click=&quot;changeName&quot;&gt;更换姓名&lt;/button&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      var vm = new new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;</span><br><span class="line">          name: &quot;zhangsan&quot;,</span><br><span class="line">        &#125;,</span><br><span class="line">        // 通过methods完成函数或方法的定义</span><br><span class="line">        methods: &#123;</span><br><span class="line">          changeName() &#123;</span><br><span class="line">            // 在methods中要获取data中的属性，需要通过this来完成，this表示的是vue实例。</span><br><span class="line">            this.name = &quot;itcast&quot;;</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;)();</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>还可以通过简写的形式。建议以后都使用简写的形式</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;button @click=&quot;changeName&quot;&gt;更换姓名&lt;/button&gt;</span><br></pre></td></tr></table></figure>

<p>带参数的形式如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;button @click=&quot;changeNameByArg(&#x27;laowang&#x27;)&quot;&gt;带参数的情况&lt;/button&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">var vm = new new Vue(&#123;</span><br><span class="line">  el: &quot;#app&quot;,</span><br><span class="line">  data: &#123;</span><br><span class="line">    name: &quot;zhangsan&quot;,</span><br><span class="line">  &#125;,</span><br><span class="line">  // 通过methods完成函数或方法的定义</span><br><span class="line">  methods: &#123;</span><br><span class="line">    changeName() &#123;</span><br><span class="line">      // 在methods中要获取data中的属性，需要通过this来完成，this表示的是vue实例。</span><br><span class="line">      this.name = &quot;itcast&quot;;</span><br><span class="line">    &#125;,</span><br><span class="line">    changeNameByArg(userName) &#123;</span><br><span class="line">      this.name = userName;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;)();</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p>除了绑定鼠标的单击事件以外，也可以绑定键盘的实际。</p>
<p>例如，页面有有一个文本框，用户在该文本框中输入内容，按下回车键，获取到用户输入的内容。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;span&gt;&#123;&#123;name&#125;&#125;&lt;/span&gt;</span><br><span class="line">      &lt;!-- 通过v-on来指定对应的事件，然后后面跟上对应的方法名，方法的定义在methods完成 --&gt;</span><br><span class="line">      &lt;button @click=&quot;changeName&quot;&gt;更换姓名&lt;/button&gt;</span><br><span class="line">      &lt;button @click=&quot;changeNameByArg(&#x27;laowang&#x27;)&quot;&gt;带参数的情况&lt;/button&gt;</span><br><span class="line">    &lt;!--给文本框添加键盘事件--&gt;</span><br><span class="line">      &lt;input type=&quot;text&quot; @keydown.enter=&quot;changeUserName&quot; v-model=&quot;name&quot; /&gt;</span><br><span class="line">    &lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>在<code>mehtods</code>中定义<code>changeUserName</code>方法</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 通过methods完成函数或方法的定义</span></span><br><span class="line">       <span class="attr">methods</span>: &#123;</span><br><span class="line">         <span class="title function_">changeName</span>(<span class="params"></span>) &#123;</span><br><span class="line">           <span class="comment">// 在methods中要获取data中的属性，需要通过this来完成，this表示的是vue实例。</span></span><br><span class="line">           <span class="variable language_">this</span>.<span class="property">name</span> = <span class="string">&quot;itcast&quot;</span>;</span><br><span class="line">         &#125;,</span><br><span class="line">         <span class="title function_">changeNameByArg</span>(<span class="params">userName</span>) &#123;</span><br><span class="line">           <span class="variable language_">this</span>.<span class="property">name</span> = userName;</span><br><span class="line">         &#125;,</span><br><span class="line">            <span class="comment">//定义处理文本框键盘事件的方法。</span></span><br><span class="line">         <span class="title function_">changeUserName</span>(<span class="params"></span>) &#123;</span><br><span class="line">           <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">name</span>);</span><br><span class="line">         &#125;,</span><br><span class="line">       &#125;,</span><br></pre></td></tr></table></figure>

<p>在上面的案例中，我们使用了按键的修饰符：<code>.enter</code>,在官方文档中，还有其它的按键修饰符，如下所示：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">https://cn.vuejs.org/v2/guide/events.html#%E6%8C%89%E9%94%AE%E4%BF%AE%E9%A5%B0%E7%AC%A6</span><br></pre></td></tr></table></figure>

<p>与之相关的就是事件修饰符，如下所示：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">https://cn.vuejs.org/v2/guide/events.html#%E4%BA%8B%E4%BB%B6%E4%BF%AE%E9%A5%B0%E7%AC%A6</span><br></pre></td></tr></table></figure>

<p>以上内容，大家可以在课下的时候，仔细看一下。</p>
<h2 id="6、Class-与-Style-绑定"><a href="#6、Class-与-Style-绑定" class="headerlink" title="6、Class 与 Style 绑定"></a>6、Class 与 Style 绑定</h2><p>这块主要内容主要与样式设置有关。</p>
<p>操作元素的 <code>class</code> 列表和内联样式是数据绑定的一个常见需求。因为它们都是 <code>attribute</code>，所以我们可以用 <code>v-bind</code> 处理它们：只需要通过表达式计算出字符串结果即可。不过，字符串拼接麻烦且易错。因此，在将 <code>v-bind</code> 用于 <code>class</code> 和 <code>style</code> 时，<code>Vue.js </code>做了专门的增强。表达式结果的类型除了字符串之外，还可以是对象或数组。</p>
<p>下面先来看一下<code>Class</code>的绑定。</p>
<p>在”列表渲染”中给每个列表项添加对应的样式。</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line">&lt;style&gt;</span><br><span class="line">   <span class="selector-class">.actived</span> &#123;</span><br><span class="line">     <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span><br><span class="line">   &#125;</span><br><span class="line"> &lt;/style&gt;</span><br></pre></td></tr></table></figure>

<p>下面给<code>li</code>列表添加上面所定义的样式。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;li v-for=&quot;(item, index) in users&quot; :key=&quot;item.id&quot; :class=&quot;&#123; actived: true &#125;&quot;&gt;</span><br><span class="line">          编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---索引:&#123;&#123;index&#125;&#125;</span><br><span class="line">        &lt;/li&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们可以看到，给<code>li</code>标签绑定了<code>class</code>属性，同时<code>actived</code>的值为<code>true</code>,表示给<code>li</code>添加<code>actived</code>样式。</p>
<p>现在有一个需求，就是当鼠标移动到列表项上的时候，更改对应的背景色。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;li</span><br><span class="line">  v-for=&quot;(item,index) in users&quot;</span><br><span class="line">  :key=&quot;item.id&quot;</span><br><span class="line">  :class=&quot;&#123;actived:selectItem===item&#125;&quot;</span><br><span class="line">  @mousemove=&quot;selectItem=item&quot;</span><br><span class="line">&gt;</span><br></pre></td></tr></table></figure>

<p>在对<code>class</code>进行绑定的时候，做了一个判断，判断一下<code>selectItem</code>是否与<code>item</code>相等，如果相等添加样式。</p>
<p>当鼠标移动到某个<code>li</code> 列表上的时候，触发<code>mousemove</code>事件，将<code>item</code>的值给<code>selectItem</code>.</p>
<p>在<code>data</code>中定义<code>selectItem</code>.</p>
<p>如下所示：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">data</span>: &#123;</span><br><span class="line">        <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">        <span class="attr">users</span>: [</span><br><span class="line">          &#123;</span><br><span class="line">            <span class="attr">id</span>: <span class="number">1</span>,</span><br><span class="line">            <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">          &#123;</span><br><span class="line">            <span class="attr">id</span>: <span class="number">2</span>,</span><br><span class="line">            <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">          &#123;</span><br><span class="line">            <span class="attr">id</span>: <span class="number">3</span>,</span><br><span class="line">            <span class="attr">name</span>: <span class="string">&quot;老王&quot;</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">        ],</span><br><span class="line">      &#125;,</span><br></pre></td></tr></table></figure>

<p>完整 代码如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;列表渲染&lt;/title&gt;</span><br><span class="line">    &lt;style&gt;</span><br><span class="line">      .actived &#123;</span><br><span class="line">        background-color: #dddddd;</span><br><span class="line">      &#125;</span><br><span class="line">    &lt;/style&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;ul&gt;</span><br><span class="line">        &lt;!-- users表示数组，item表示从数组中取出的对象,这个名字可以随意取 --&gt;</span><br><span class="line">        &lt;!-- 注意 v-for必须结合key属性来使用，它会唯一标识数组中的每一项，未来当数组中的那一项改变的时候，它会只更新那一项，好处就是提升性能。注意key的值唯一，不能重复 --&gt;</span><br><span class="line">        &lt;!-- index表示数组的索引值，该名字可以随意定义 --&gt;</span><br><span class="line">        &lt;li</span><br><span class="line">          v-for=&quot;(item, index) in users&quot;</span><br><span class="line">          :key=&quot;item.id&quot;</span><br><span class="line">          :class=&quot;&#123; actived: selectItem === item &#125;&quot;</span><br><span class="line">          @mousemove=&quot;selectItem = item&quot;</span><br><span class="line">        &gt;</span><br><span class="line">          编号：&#123;&#123; item.id &#125;&#125; 姓名:&#123;&#123; item.name &#125;&#125;---索引:&#123;&#123; index &#125;&#125;</span><br><span class="line">        &lt;/li&gt;</span><br><span class="line">      &lt;/ul&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script src=&quot;vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;</span><br><span class="line">          selectItem: &quot;&quot;,</span><br><span class="line">          users: [</span><br><span class="line">            &#123;</span><br><span class="line">              id: 1,</span><br><span class="line">              name: &quot;张三&quot;,</span><br><span class="line">            &#125;,</span><br><span class="line">            &#123;</span><br><span class="line">              id: 2,</span><br><span class="line">              name: &quot;李四&quot;,</span><br><span class="line">            &#125;,</span><br><span class="line">            &#123;</span><br><span class="line">              id: 3,</span><br><span class="line">              name: &quot;老王&quot;,</span><br><span class="line">            &#125;,</span><br><span class="line">          ],</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>下面，我们再来看一下<code>Style</code>的绑定。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;li</span><br><span class="line">  v-for=&quot;(item, index) in users&quot;</span><br><span class="line">  :key=&quot;item.id&quot;</span><br><span class="line">  :style=&quot;&#123; backgroundColor: selectItem === item ? &#x27;#dddddd&#x27; : &#x27;transparent&#x27; &#125;&quot;</span><br><span class="line">  @mousemove=&quot;selectItem = item&quot;</span><br><span class="line">&gt;</span><br><span class="line">          编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---索引:&#123;&#123;index&#125;&#125;</span><br><span class="line">        &lt;/li&gt;</span><br></pre></td></tr></table></figure>

<p>通过上面的代码，可以看到通过绑定<code>style</code>的方式来处理样式是非常麻烦的。</p>
<h2 id="7、条件渲染"><a href="#7、条件渲染" class="headerlink" title="7、条件渲染"></a>7、条件渲染</h2><p>v-if 和 v-show 指令可以用来控制元素的显示和隐藏</p>
<p>下面，我们先来看一下<code>v-if</code>的应用。</p>
<p>这里还是对用户数据进行判断。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;p v-if=&quot;users.length===0&quot;&gt;没有任何用户数据&lt;/p&gt;</span><br><span class="line"></span><br><span class="line">      &lt;ul v-else&gt;</span><br><span class="line">        &lt;!-- users表示数组，item表示从数组中取出的对象,这个名字可以随意取 --&gt;</span><br><span class="line">        &lt;!-- 注意 v-for必须结合key属性来使用，它会唯一标识数组中的每一项，未来当数组中的那一项改变的时候，它会只更新那一项，好处就是提升性能。注意key的值唯一，不能重复 --&gt;</span><br><span class="line">        &lt;!-- index表示数组的索引值，该名字可以随意定义 --&gt;</span><br><span class="line">        &lt;!-- &lt;li</span><br><span class="line">          v-for=&quot;(item,index) in users&quot;</span><br><span class="line">          :key=&quot;item.id&quot;</span><br><span class="line">          :class=&quot;&#123;actived:selectItem===item&#125;&quot;</span><br><span class="line">          @mousemove=&quot;selectItem=item&quot;</span><br><span class="line">        &gt;</span><br><span class="line">          编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---索引:&#123;&#123;index&#125;&#125;</span><br><span class="line">        &lt;/li&gt; --&gt;</span><br><span class="line"></span><br><span class="line">        &lt;li</span><br><span class="line">          v-for=&quot;(item,index) in users&quot;</span><br><span class="line">          :key=&quot;item.id&quot;</span><br><span class="line">          :style=&quot;&#123;backgroundColor:selectItem===item?&#x27;#dddddd&#x27;:&#x27;transparent&#x27;&#125;&quot;</span><br><span class="line">          @mousemove=&quot;selectItem=item&quot;</span><br><span class="line">        &gt;</span><br><span class="line">          编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---索引:&#123;&#123;index&#125;&#125;</span><br><span class="line">        &lt;/li&gt;</span><br><span class="line">      &lt;/ul&gt;</span><br><span class="line">    &lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们首先对<code>users</code>数组做了一个判断，如果没有数据，就在页面上展示：“没有任何用户数据”</p>
<p>否则渲染整个列表。</p>
<p>上面是关于<code>v-if</code>的使用，下面看一下<code>v-show</code>.</p>
<p><code>v-show</code> 是通过<code>css</code>属性<code>display</code>控制元素显示，元素总是存在的。</p>
<p><code>v-if</code>:通过控制<code>dom</code>来控制元素的显示和隐藏,如果一开始条件为<code>false</code>,元素是不存在的。</p>
<p>什么时候使用<code>v-show</code>,什么时候使用<code>v-if</code>呢？</p>
<p>如果需要频繁的控制元素的显示与隐藏，建议使用<code>v-show</code>. 从而避免大量<code>DOM</code>操作，提高性能。</p>
<p>而如果某个元素满足条件后，渲染到页面中，并且以后变化比较少，可以使用<code>v-if</code></p>
<h2 id="8、计算属性"><a href="#8、计算属性" class="headerlink" title="8、计算属性"></a>8、计算属性</h2><p>计算属性出现的目的是解决模板中放入过多的逻辑会让模板过重且难以维护的问题.</p>
<p>计算属性是根据 data 中已有的属性，计算得到一个新的属性.</p>
<p>下面，我们可以通过一个案例来学习一下计算属性、</p>
<p>在一个文本框中输入第一个名字，第二个文本框中输入第二个名字，然后展示全部名称。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">        &lt;input type=&quot;text&quot; v-model=&quot;firstName&quot;&gt;</span><br><span class="line">        &lt;input type=&quot;text&quot; v-model=&quot;lastName&quot;&gt;</span><br><span class="line">        &lt;!-- 这样是模板逻辑变得非常复杂，不易维护 --&gt;</span><br><span class="line">        &lt;div&gt;全名：&#123;&#123;firstName + lastName&#125;&#125;&lt;/div&gt;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        &lt;div&gt;全名：&#123;&#123;fullName&#125;&#125;&lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">        var vm = new Vue(&#123;</span><br><span class="line">            el: &#x27;#app&#x27;,</span><br><span class="line">            data: &#123;</span><br><span class="line">                firstName: &#x27;&#x27;,</span><br><span class="line">                lastName: &#x27;&#x27;</span><br><span class="line">            &#125;,</span><br><span class="line">            // 创建计算属性通过computed关键字，它是一个对象</span><br><span class="line">            computed: &#123;</span><br><span class="line">                // 这里fullName就是一个计算属性，它是一个函数，但这个函数可以当成属性来使用</span><br><span class="line">                fullName() &#123;</span><br><span class="line">                    return this.firstName + this.lastName</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">&lt;/body&gt;</span><br></pre></td></tr></table></figure>

<p>了解了计算属性后，下面对用户列表添加一个功能，要求是计算总人数。</p>
<p>可以在<code>ul</code>列表下面，添加如下的代码。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;p&gt;</span><br><span class="line">  总人数：&#123;&#123;users.length+&quot;个&quot;&#125;&#125;</span><br><span class="line">&lt;/p&gt;</span><br></pre></td></tr></table></figure>

<p>最终展示出了，对应的人数，但是这里在模板中做了运算（在这里做了字符串拼接，虽然计算简单，但是最好还是通过计算属性来完成），为了防止在模板中放入过多的逻辑计算，这里可以使用计算属性来解决。</p>
<p>下面对代码进行改造：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;p&gt;</span><br><span class="line">        &lt;!-- 总人数：&#123;&#123;users.length+&quot;个&quot;&#125;&#125; --&gt;</span><br><span class="line">        总人数：&#123;&#123;total&#125;&#125;</span><br><span class="line">      &lt;/p&gt;</span><br></pre></td></tr></table></figure>

<p>计算属性实现：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">new Vue(&#123;</span><br><span class="line">  el: &quot;#app&quot;,</span><br><span class="line">  data: &#123;</span><br><span class="line">    selectItem: &quot;&quot;,</span><br><span class="line">    users: [</span><br><span class="line">      &#123;</span><br><span class="line">        id: 1,</span><br><span class="line">        name: &quot;张三&quot;,</span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        id: 2,</span><br><span class="line">        name: &quot;李四&quot;,</span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        id: 3,</span><br><span class="line">        name: &quot;老王&quot;,</span><br><span class="line">      &#125;,</span><br><span class="line">    ],</span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  computed: &#123;</span><br><span class="line">    total() &#123;</span><br><span class="line">      // 计算属性是有缓存性：如果值没有发生变化，则页面不会重新渲染</span><br><span class="line">      return this.users.length + &quot;个&quot;;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">v</span><br></pre></td></tr></table></figure>

<p>通过上面的代码，可以看到使用计算属性，让界面变得更加的简洁。</p>
<p>使用计算属性还有一个好处：</p>
<p>其实细心的话就会发现，调用 methods 里的方法也能实现和计算属性一样的效果，既然使用 methods 就可以实现，那为什么还需要计算属性呢？原因就是计算属性是基于他的依赖缓存的（所依赖的还是<code>data</code>中的数据）。一个计算属性所依赖的数据发生变化时，他才会重新取值</p>
<p>也就是说：只要相关依赖没有改变，对此访问计算属性得到的是之前缓 存的结果，不会多次执行。</p>
<p>下面我们测试一下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;p&gt;</span><br><span class="line">        &lt;!-- 总人数：&#123;&#123;users.length+&quot;个&quot;&#125;&#125; --&gt;</span><br><span class="line">        总人数：&#123;&#123;total&#125;&#125; 总人数：&#123;&#123;total&#125;&#125;</span><br><span class="line">      &lt;/p&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们使用<code>total</code>了两次。</p>
<p>下面在看一下关于计算属性中的代码修改：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">computed: &#123; total() &#123; console.log(&quot;aaa&quot;); //</span><br><span class="line">计算属性是有缓存性：如果值没有发生变化，则页面不会重新渲染 return</span><br><span class="line">this.users.length + &quot;个&quot;; &#125;, &#125;,</span><br></pre></td></tr></table></figure>

<p>这里，我们通过<code>console</code>输出字符串<code>aaa</code>,但是在控制台上只是输出了一次，因为，第二次使用<code>total</code>的时候，发现值没有变化，所以直接从缓存中获取了对应的值。并没有重新进行计算，这样带来的好处就是，性能得到了提升。</p>
<p>下面，我们换成<code>methods</code>函数的形式来看一下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;p&gt;</span><br><span class="line">        &lt;!-- 总人数：&#123;&#123;users.length+&quot;个&quot;&#125;&#125; --&gt;</span><br><span class="line">        总人数：&#123;&#123;total&#125;&#125; 总人数：&#123;&#123;total&#125;&#125; 总人数：&#123;&#123;getTotal()&#125;&#125;</span><br><span class="line">        总人数：&#123;&#123;getTotal()&#125;&#125;</span><br><span class="line">      &lt;/p&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，调用了两次<code>getTotal</code>方法。</p>
<p><code>getTotal</code>方法的实现如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">methods</span>: &#123;</span><br><span class="line">        <span class="attr">getTotal</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">          <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;methods&quot;</span>);</span><br><span class="line">          <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> + <span class="string">&quot;个&quot;</span>;</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;,</span><br></pre></td></tr></table></figure>

<p>实现的方式是差不多的，但是这里却执行了两次。（注意：由于本案例中给每一个<code>li</code>标签添加了<code> *@mousemove*</code>,所以只要鼠标移动到列表上，就会导致页面重新渲染，这时会不断的调用<code>getTotal</code>方法。）</p>
<p>所以通过上面案例的演示，可以明确的看出计算属性是有缓存的，也就是所依赖的<code>data</code>属性中的数据没有变化，那么是不会重新计算的。所以提升了对应的性能。</p>
<p>所以说，在进行大量耗时计算的时候，建议使用计算属性来完成。</p>
<p>如下代码：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">data</span>: &#123;</span><br><span class="line">         <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">         <span class="attr">num</span>: <span class="number">100</span></span><br><span class="line">         &#125;</span><br></pre></td></tr></table></figure>

<p>在<code>data</code>中定义了<code>num</code> 属性，并且初始值为 100、</p>
<p>下面在计算属性中进行求和的运算，代码实现如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">computed</span>: &#123;</span><br><span class="line">         <span class="title function_">total</span>(<span class="params"></span>) &#123;</span><br><span class="line">           <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;aaa&quot;</span>);</span><br><span class="line">           <span class="comment">// 计算属性是有缓存性：如果值没有发生变化，则页面不会重新渲染</span></span><br><span class="line">           <span class="comment">// return this.users.length + &quot;个&quot;;</span></span><br><span class="line">           <span class="keyword">let</span> count = <span class="number">0</span>;</span><br><span class="line">           <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt;= <span class="variable language_">this</span>.<span class="property">num</span>; i++) &#123;</span><br><span class="line">             count += i;</span><br><span class="line">           &#125;</span><br><span class="line">           <span class="keyword">return</span> count;</span><br><span class="line">         &#125;,</span><br><span class="line">       &#125;,</span><br></pre></td></tr></table></figure>

<p>通过演示，可以发现计算属性只是在第一次调用的时候，执行了一次，后续由于所依赖的数据<code>num</code>没有发生变化，所以即时调用多次，也并没有重新进行计算，而是获取上次计算的结果，所以说在进行大量耗时计算的时候，通过计算属性可以提升性能。</p>
<h2 id="9、侦听器"><a href="#9、侦听器" class="headerlink" title="9、侦听器"></a>9、侦听器</h2><p>侦听器就是侦听<code>data</code>中的数据变化，如果数据一旦发生变化就通知侦听器所绑定方法，来执行相应的操作。从这一点上，与计算属性是非常类似的。</p>
<p>但是，侦听器也有自己独有的应用场景。</p>
<p>执行异步或开销较大的操作。</p>
<p>下面，先来看一下侦听器的基本使用</p>
<p>我们使用侦听器来统计总人数。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;p&gt;</span><br><span class="line">   </span><br><span class="line">        总人数：&#123;&#123;totalCount&#125;&#125;</span><br><span class="line">      &lt;/p&gt;</span><br></pre></td></tr></table></figure>

<p>在<code>data</code>中定义<code>totalCount</code>属性。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">data</span>: &#123;</span><br><span class="line">         <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">         <span class="attr">num</span>: <span class="number">100</span>,</span><br><span class="line">         <span class="attr">totalCount</span>: <span class="number">0</span></span><br><span class="line">      &#125;</span><br></pre></td></tr></table></figure>

<p>使用<code>watch</code>来监听<code>users</code>数组的数据变化。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">watch</span>: &#123;</span><br><span class="line">       <span class="attr">users</span>: &#123;</span><br><span class="line">         <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="comment">//立即执行</span></span><br><span class="line">         <span class="title function_">handler</span>(<span class="params">newValue, oldValue</span>) &#123;</span><br><span class="line">           <span class="variable language_">this</span>.<span class="property">totalCount</span> = newValue.<span class="property">length</span> + <span class="string">&quot;个人&quot;</span>;</span><br><span class="line">         &#125;,</span><br><span class="line">       &#125;,</span><br><span class="line">     &#125;</span><br></pre></td></tr></table></figure>

<p>当<code>users</code>数组发生了变化后，就会执行<code>handler</code>这个函数，同时用于加上了<code>immediate</code>属性，并且该属性的值为<code>true</code>，表示的就是在初始化绑定的时候，也会去执行侦听器。因为<code>watch</code>在初始化绑定的时候是不会执行的，等到所监听的内容改变之后才会去侦听执行。</p>
<p>以上就是<code>watch</code>侦听器的基本使用，但是通过这个案例，我们发现还是使用计算属性来统计总人数更加的方便一些。</p>
<p>当然，侦听器有自己的应用场景，它的应用场景就是在执行异步请求或者进行开销比较大的操作的时候，会使用侦听器。</p>
<p>下面我们在通过一个案例，来体会一下<code>watch</code>侦听器的应用场景。</p>
<p>下面我们来看一个异步操作的情况。就是当用户在一个文本框中输入了用户名以后，要将输入的用户名发送到服务端，来检查该用户名是否已经被占用。</p>
<p>具体的实现代码如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;侦听器&lt;/title&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;div&gt;</span><br><span class="line">        &lt;span&gt;用户名&lt;/span&gt;</span><br><span class="line">        &lt;!--这里使用了lazy,保证当文本框失去焦点后，才去执行对应操作--&gt;</span><br><span class="line">        &lt;span&gt;&lt;input type=&quot;text&quot; v-model.lazy=&quot;uname&quot; /&gt;&lt;/span&gt;</span><br><span class="line">        &lt;span&gt;&#123;&#123; message &#125;&#125;&lt;/span&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      const vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;</span><br><span class="line">          uname: &quot;&quot;,</span><br><span class="line">          message: &quot;&quot;,</span><br><span class="line">        &#125;,</span><br><span class="line">        methods: &#123;</span><br><span class="line">          checkUserName: function (userName) &#123;</span><br><span class="line">            let that = this;</span><br><span class="line">            setTimeout(function () &#123;</span><br><span class="line">              if (userName === &quot;admin&quot;) &#123;</span><br><span class="line">                that.message = &quot;用户名已经存在,请更改....&quot;;</span><br><span class="line">              &#125; else &#123;</span><br><span class="line">                that.message = &quot;该用户名可以使用.....&quot;;</span><br><span class="line">              &#125;</span><br><span class="line">            &#125;, 3000);</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">        watch: &#123;</span><br><span class="line">          uname: function (value) &#123;</span><br><span class="line">            //调用后台接口，来验证用户名是被占用</span><br><span class="line">            this.checkUserName(value);</span><br><span class="line">            this.message = &quot;正在校验用户名....&quot;;</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>以上的案例，就是通过<code>watch</code>来监听<code>uname</code>的值是否发生变化，如果发生了变化，就通过发送异步请求来检查<code>uname</code>中的值，是否已经被占用。</p>
<p>通过以上的案例：我们可以看到<code>watch</code>是允许异步操作的，并且在我们得到最终的结果前，可以设置中间状态，这些都是计算属性无法做到的。</p>
<p>最后我们把计算属性与侦听器做一个总结，看一下它们的应用场景。</p>
<p>第一点：语境上的差异：</p>
<p><code>watch</code>适合一个值发生了变化，对应的要做一些其它的事情，适合一个值影响多个值的情形。</p>
<p>例如，上面案例中的用户名检测，这里是一个<code>uname</code>发生了变化，但是这里做了很多其它的事情，例如修改<code>message</code>的值，发送异步请求。</p>
<p>而计算属性<code>computed</code>:一个值由其它的值得来，其它值发生了变化，对应的值也会变化，适合做多个值影响一个值的情形。</p>
<p>例如如下代码：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">computed</span>:&#123;</span><br><span class="line">    <span class="title function_">fullName</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">firstName</span>+<span class="string">&#x27; &#x27;</span>+<span class="variable language_">this</span>.<span class="property">lastName</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>第二点：计算属性有缓存性。</p>
<p>由于这个特点，我们在实际的应用中，能用计算属性的，会首先考虑先使用计算属性。</p>
<p>第三点：侦听器选项提供了更加通用的方法，适合执行异步操作或者较大开销操作。</p>
<h2 id="10、生命周期简介"><a href="#10、生命周期简介" class="headerlink" title="10、生命周期简介"></a>10、生命周期简介</h2><p>每个<code>Vue</code>实例在被创建时都要经过一系列的初始化过程，例如：需要设置数据的监听，编译模板，将实例挂载到<code>DOM</code>上，并且在数据变化时更新<code>DOM</code>等，这些过程统称为<code>Vue</code>实例的<code>生命周期</code>。同时在这个过程中也会运行一些叫做<strong>生命周期钩子</strong>的函数，这给了用户在不同阶段添加自己的代码的机会。</p>
<p>下面，我们来看一下这些钩子函数的应用。</p>
<p>通过一个异步获取列表数据的案例，来查看这些生命周期的钩子函数应用。</p>
<p>在这里是通过异步的方式获取用户列表的数据。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&lt;!<span class="variable constant_">DOCTYPE</span> html&gt;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>列表渲染<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span></span><br><span class="line"><span class="language-css"><span class="language-xml">      <span class="selector-class">.actived</span> &#123;</span></span></span><br><span class="line"><span class="language-css"><span class="language-xml">        <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span></span></span><br><span class="line"><span class="language-css"><span class="language-xml">      &#125;</span></span></span><br><span class="line"><span class="language-css"><span class="language-xml">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">p</span> <span class="attr">v-if</span>=<span class="string">&quot;users.length===0&quot;</span>&gt;</span>没有任何用户数据<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">ul</span> <span class="attr">v-else</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="comment">&lt;!-- users表示数组，item表示从数组中取出的对象,这个名字可以随意取 --&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="comment">&lt;!-- 注意 v-for必须结合key属性来使用，它会唯一标识数组中的每一项，未来当数组中的那一项改变的时候，它会只更新那一项，好处就是提升性能。注意key的值唯一，不能重复 --&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="comment">&lt;!-- index表示数组的索引值，该名字可以随意定义 --&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="comment">&lt;!-- &lt;li</span></span></span><br><span class="line"><span class="comment"><span class="language-xml">          v-for=&quot;(item,index) in users&quot;</span></span></span><br><span class="line"><span class="comment"><span class="language-xml">          :key=&quot;item.id&quot;</span></span></span><br><span class="line"><span class="comment"><span class="language-xml">          :class=&quot;&#123;actived:selectItem===item&#125;&quot;</span></span></span><br><span class="line"><span class="comment"><span class="language-xml">          @mousemove=&quot;selectItem=item&quot;</span></span></span><br><span class="line"><span class="comment"><span class="language-xml">        &gt;</span></span></span><br><span class="line"><span class="comment"><span class="language-xml">          编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---索引:&#123;&#123;index&#125;&#125;</span></span></span><br><span class="line"><span class="comment"><span class="language-xml">        &lt;/li&gt; --&gt;</span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">li</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">          <span class="attr">v-for</span>=<span class="string">&quot;(item,index) in users&quot;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">          <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">          <span class="attr">:style</span>=<span class="string">&quot;&#123;backgroundColor:selectItem===item?&#x27;#dddddd&#x27;:&#x27;transparent&#x27;&#125;&quot;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">          @<span class="attr">mousemove</span>=<span class="string">&quot;selectItem=item&quot;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">        &gt;</span></span></span><br><span class="line"><span class="language-xml">          编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---索引:&#123;&#123;index&#125;&#125;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="comment">&lt;!-- 总人数：&#123;&#123;users.length+&quot;个&quot;&#125;&#125; --&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="comment">&lt;!-- 总人数：&#123;&#123;total&#125;&#125; 总人数：&#123;&#123;total&#125;&#125; 总人数：&#123;&#123;getTotal()&#125;&#125;</span></span></span><br><span class="line"><span class="comment"><span class="language-xml">        总人数：&#123;&#123;getTotal()&#125;&#125; --&gt;</span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">        总人数：&#123;&#123;totalCount&#125;&#125;</span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">      <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">data</span>: &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          <span class="attr">num</span>: <span class="number">100</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">            <span class="comment">//指定users默认数据为一个空数组。</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          <span class="attr">users</span>: [],</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//组件实例已创建时，执行created方法，来调用getUserList方法，发送异步请求获取数据</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//将获取到的数据交个users这个状态数组。</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="keyword">async</span> <span class="title function_">created</span>(<span class="params"></span>) &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          <span class="keyword">const</span> users = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">getUserList</span>();</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          <span class="variable language_">this</span>.<span class="property">users</span> = users;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">methods</span>: &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          <span class="attr">getTotal</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;methods&quot;</span>);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> + <span class="string">&quot;个&quot;</span>;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">            <span class="comment">//在getUserList方法中，模拟一个异步请求。</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          <span class="attr">getUserList</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">              <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                <span class="title function_">resolve</span>([</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                  &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    <span class="attr">id</span>: <span class="number">1</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                  &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                  &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    <span class="attr">id</span>: <span class="number">2</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                  &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                  &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    <span class="attr">id</span>: <span class="number">3</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    <span class="attr">name</span>: <span class="string">&quot;老王&quot;</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                  &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                ]);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">              &#125;, <span class="number">2000</span>);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">            &#125;);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">watch</span>: &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          <span class="attr">users</span>: &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">            <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="comment">//立即执行</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">            <span class="title function_">handler</span>(<span class="params">newValue, oldValue</span>) &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">              <span class="variable language_">this</span>.<span class="property">totalCount</span> = newValue.<span class="property">length</span> + <span class="string">&quot;个人&quot;</span>;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">            &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">          &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">// computed: &#123;</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//   total() &#123;</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//     console.log(&quot;aaa&quot;);</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//     // 计算属性是有缓存性：如果值没有发生变化，则页面不会重新渲染</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//     // return this.users.length + &quot;个&quot;;</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//     let count = 0;</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//     for (let i = 0; i &lt;= this.num; i++) &#123;</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//       count += i;</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//     &#125;</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//     return count;</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">//   &#125;,</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="comment">// &#125;,</span></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">      &#125;);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>上面的代码，还是对原有的“列表渲染”内容进行更改。</p>
<p>第一：将<code>users</code>的值定义为空数组</p>
<p>第二：定义<code>getUserList</code>方法，在该方法中模拟异步操作，最终返回的是一个<code>Promise</code>对象。</p>
<p>第三：在<code>created</code>阶段调用<code>getUserList</code>方法来获取数据，将获取到的数据赋值给<code>users</code>这个状态数组，注意这里需要将<code>created</code>修改成<code>async</code>与<code>await</code>的形式。同时还要注意<code>created</code>的执行时机：组件实例已创建时，执行 created 方法。</p>
<p>现在已经对生命周期有了一个简单的了解，下面我们继续探讨生命周期的内容。</p>
<h2 id="11、生命周期探讨"><a href="#11、生命周期探讨" class="headerlink" title="11、生命周期探讨"></a>11、生命周期探讨</h2><p>在这一小节中，我们看一下<code>vue</code>生命周期中其它的一些钩子函数内容。</p>
<p>其实<code>Vue</code>实例的生命周期，主要分为三个阶段，分别为</p>
<ul>
<li>挂载(初始化相关属性,例如<code>watch</code>属性，<code>method</code>属性)<ol>
<li><code>beforeCreate</code></li>
<li><code>created</code></li>
<li><code>beforeMount</code></li>
<li><code>mounted</code></li>
</ol>
</li>
<li>更新(元素或组件的变更操作)<ol>
<li><code>beforeUpdate</code></li>
<li><code>updated</code></li>
</ol>
</li>
<li>销毁（销毁相关属性）<ol>
<li><code>beforeDestroy</code></li>
<li><code>destroyed</code></li>
</ol>
</li>
</ul>
<p>下面，我们再来看一道面试题：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">关于Vue的生命周期，下列哪项是不正确的？()[单选题]</span><br><span class="line">A、Vue 实例从创建到销毁的过程，就是生命周期。</span><br><span class="line">B、页面首次加载会触发beforeCreate, created, beforeMount, mounted, beforeUpdate, updated。</span><br><span class="line">C、created表示完成数据观测，属性和方法的运算，初始化事件，$el属性还没有显示出来。</span><br><span class="line">D、DOM渲染在mounted中就已经完成了。</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>分析：</p>
<p>选项<code>A</code>是没有问题的，<code>Vue</code>实例从创建到销毁的过程就是生命周期。</p>
<p>关于<code>B</code>选项，我们可以通过写一个程序来进行验证。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;生命周期&lt;/title&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;&#123;&#123; foo &#125;&#125;&lt;/div&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      const vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;</span><br><span class="line">          foo: &quot;foo&quot;,</span><br><span class="line">        &#125;,</span><br><span class="line">        beforeCreate() &#123;</span><br><span class="line">          console.log(&quot;beforCreate&quot;);</span><br><span class="line">        &#125;,</span><br><span class="line">        created() &#123;</span><br><span class="line">          console.log(&quot;created&quot;);</span><br><span class="line">        &#125;,</span><br><span class="line">        beforeMount() &#123;</span><br><span class="line">          console.log(&quot;beforeMount&quot;);</span><br><span class="line">        &#125;,</span><br><span class="line">        mounted() &#123;</span><br><span class="line">          console.log(&quot;mounted&quot;);</span><br><span class="line">        &#125;,</span><br><span class="line">        beforeUpdate() &#123;</span><br><span class="line">          console.log(&quot;beforeUpdate&quot;);</span><br><span class="line">        &#125;,</span><br><span class="line">        updated() &#123;</span><br><span class="line">          console.log(&quot;updated&quot;);</span><br><span class="line">        &#125;,</span><br><span class="line">        beforeDestroy() &#123;</span><br><span class="line">          console.log(&quot;beforeDestroy&quot;);</span><br><span class="line">        &#125;,</span><br><span class="line">        destroyed() &#123;</span><br><span class="line">          console.log(&quot;destroyed&quot;);</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">    &lt;script&gt;&lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们将所有的钩子函数都添加上了，然后打开浏览器，看下执行结果：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">beforCreate</span><br><span class="line">created</span><br><span class="line">beforeMount</span><br><span class="line">mounted</span><br></pre></td></tr></table></figure>

<p>以上就是初次加载时所执行的钩子函数，并没有<code>beforeUpdate</code> 与<code>updated</code>,所以选项<code>B</code>是错误的。</p>
<p>那么<code>beforeUpdate</code>与<code>updated</code>什么时候会执行呢？是在，组件或者是元素更新的时候。</p>
<p>下面，我们来测试一下，看一下效果。</p>
<p>首先增加一个”更新”按钮</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &#123;&#123;foo&#125;&#125;</span><br><span class="line">      &lt;button @click=&quot;update&quot;&gt;更新&lt;/button&gt;</span><br><span class="line">    &lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>对应的<code>update</code>方法的实现如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">methods</span>: &#123;</span><br><span class="line">        <span class="attr">update</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">          <span class="variable language_">this</span>.<span class="property">foo</span> = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;,</span><br></pre></td></tr></table></figure>

<p>在<code>update</code>方法中，修改了<code>foo</code>属性的值。打开浏览器，单击“更新”按钮后，看到的效果如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">beforeUpdate</span><br><span class="line">updated</span><br></pre></td></tr></table></figure>

<p>通过以上的测试，可以验证在更新元素的时候，会执行在“更新”阶段的钩子函数。</p>
<p>下面，我们在测试一下，看一下“销毁”阶段的钩子函数的执行。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &#123;&#123;foo&#125;&#125;</span><br><span class="line">      &lt;button @click=&quot;update&quot;&gt;更新&lt;/button&gt;</span><br><span class="line">      &lt;button @click=&quot;destroy&quot;&gt;销毁&lt;/button&gt;</span><br><span class="line">    &lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中增加了一个销毁的按钮，对应的<code>destroy</code>方法的实现如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">methods</span>: &#123;</span><br><span class="line">      <span class="attr">update</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">foo</span> = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="attr">destroy</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">        <span class="comment">//销毁资源</span></span><br><span class="line">        <span class="variable language_">this</span>.$destroy();</span><br><span class="line">      &#125;,</span><br><span class="line">    &#125;,</span><br></pre></td></tr></table></figure>

<p>在<code>destroy</code>方法中，调用了系统中的<code>$destroy</code>方法销毁了所有资源，这时会触发销毁阶段的钩子函数，所以这时会输出</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">beforeDestroy</span><br><span class="line">destroyed</span><br></pre></td></tr></table></figure>

<p>这时，如果你去单击“更新”按钮，就会发现什么效果也没有了，也就是无法完成元素的更新了，因为元素已经被销毁了。</p>
<p>下面，我们通过官方的生命周期图来再次看一下整个生命周期的流程。也是为了看一下上面所出题的<code>C</code>和<code>D</code>的选项是说法否正确。</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/lifecycle.png"></p>
<p><code>beforeCreate</code>: <code>Vue</code>实例初始化之后，以及事件初始化，以及组件的父子关系确定后执行该钩子函数，一般在开发中很少使用</p>
<p><code>created</code>: 在调用该方法之前，初始化会被使用到的状态，状态包括<code>props</code>,<code>methods</code>,<code>data</code>,<code>computed</code>,<code>watch</code>.</p>
<p>而且会实现对<code>data</code>中属性的监听，也就是在<code>created</code>的时候数据已经和<code>data</code>属性进行了绑定。(放在<code>data</code>中的属性当值发生改变的时候，视图也会改变)。同时也会对传递到组件中的数据进行校验。</p>
<p>所以在执行<code>created</code>的时候，所有的状态都初始化完成，我们也完全可以在该阶段发送异步的<code>ajax</code>请求，获取数据。</p>
<p>但是，在<code>created</code>方法中，是无法获取到对应的的<code>$el</code>选项,也就是无法获取<code>Dom</code>. 所以说上题中选项<code>c</code>的说法是正确的。</p>
<p>如下代码所示：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">created</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;created&quot;</span>);</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;el===&quot;</span>, <span class="variable language_">this</span>.<span class="property">$el</span>);<span class="comment">// undefined</span></span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;data==&quot;</span>, <span class="variable language_">this</span>.<span class="property">$data</span>);<span class="comment">// 可以获取数据</span></span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;foo==&quot;</span>, <span class="variable language_">this</span>.<span class="property">foo</span>);<span class="comment">//可以获取数据</span></span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>

<p><code>created</code>方法执行完毕后，下面会判断对象中有没有<code>el</code>选项。如果有，继续执行下面的流程，也就是判断是否有<code>template</code>选项，如果没有<code>el</code>选项，则停止整个生命周期的流程，直到执行了<code>vm.$mount(el)</code></p>
<p>后，才会继续向下执行生命周期的流程。</p>
<p>下面我们测试一下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">const vm = new Vue(&#123;</span><br><span class="line">  // el: &quot;#app&quot;,  //去掉了el选项</span><br><span class="line">  data: &#123;</span><br><span class="line">    foo: &quot;fooData&quot;,</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;</span><br><span class="line">    update: function () &#123;</span><br><span class="line">      this.foo = &quot;hello&quot;;</span><br><span class="line">    &#125;,</span><br><span class="line">    destroy: function () &#123;</span><br><span class="line">      //销毁资源</span><br><span class="line">      this.$destroy();</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeCreate() &#123;</span><br><span class="line">    console.log(&quot;beforCreate&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  created() &#123;</span><br><span class="line">    console.log(&quot;created&quot;);</span><br><span class="line">    console.log(&quot;el===&quot;, this.$el);</span><br><span class="line">    console.log(&quot;data==&quot;, this.$data);</span><br><span class="line">    console.log(&quot;foo==&quot;, this.foo);</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeMount() &#123;</span><br><span class="line">    console.log(&quot;beforeMount&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  mounted() &#123;</span><br><span class="line">    console.log(&quot;mounted&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeUpdate() &#123;</span><br><span class="line">    console.log(&quot;beforeUpdate&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  updated() &#123;</span><br><span class="line">    console.log(&quot;updated&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeDestroy() &#123;</span><br><span class="line">    console.log(&quot;beforeDestroy&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  destroyed() &#123;</span><br><span class="line">    console.log(&quot;destroyed&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们将<code>el</code>选项去掉了，运行上面的代码后，我们发现执行完<code>created</code>方法后，整个流程就停止了。</p>
<p>现在，我们不添加<code>el</code>选项，但是手动执行<code>vm.$mount(el)</code>,也能够使暂停的生命周期进行下去。</p>
<p>如下代码所示：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">const vm = new Vue(&#123;</span><br><span class="line">  // el: &quot;#app&quot;,//去掉了el选项</span><br><span class="line">  data: &#123;</span><br><span class="line">    foo: &quot;fooData&quot;,</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;</span><br><span class="line">    update: function () &#123;</span><br><span class="line">      this.foo = &quot;hello&quot;;</span><br><span class="line">    &#125;,</span><br><span class="line">    destroy: function () &#123;</span><br><span class="line">      //销毁资源</span><br><span class="line">      this.$destroy();</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeCreate() &#123;</span><br><span class="line">    console.log(&quot;beforCreate&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  created() &#123;</span><br><span class="line">    console.log(&quot;created&quot;);</span><br><span class="line">    console.log(&quot;el===&quot;, this.$el);</span><br><span class="line">    console.log(&quot;data==&quot;, this.$data);</span><br><span class="line">    console.log(&quot;foo==&quot;, this.foo);</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeMount() &#123;</span><br><span class="line">    console.log(&quot;beforeMount&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  mounted() &#123;</span><br><span class="line">    console.log(&quot;mounted&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeUpdate() &#123;</span><br><span class="line">    console.log(&quot;beforeUpdate&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  updated() &#123;</span><br><span class="line">    console.log(&quot;updated&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeDestroy() &#123;</span><br><span class="line">    console.log(&quot;beforeDestroy&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">  destroyed() &#123;</span><br><span class="line">    console.log(&quot;destroyed&quot;);</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br><span class="line">vm.$mount(&quot;#app&quot;); //添加了$mount方法</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p>运行上面的代码，可以看到，虽然<code>vm</code>对象中没有<code>el</code>参数，但是通过<code>$mount(el)</code>动态添加的方式，也能够使生命周期顺利进行。</p>
<p>我们继续向下看，就是判断在对象中是否有<code>template</code>选项。</p>
<p>第一：如果<code>Vue</code>实例对象中有<code>template</code>参数选项，则将其作为模板编译成<code>render</code>函数，来完成渲染。</p>
<p>第二：如果没有<code>template</code>参数选项，则将外部的<code>HTML作</code>为模板编译（<code>template</code>），也就是说，<code>template</code>参数选项的优先级要比外部的<code>HTML</code>高</p>
<p>第三：如果第一条,第二条件都不具备，则报错</p>
<p>下面，我们看一下添加<code>template</code>的情况。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;生命周期2&lt;/title&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;&lt;/div&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      const vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        template: &quot;&lt;p&gt;Hello &#123;&#123;message&#125;&#125;&lt;/p&gt;&quot;,</span><br><span class="line">        data: &#123;</span><br><span class="line">          message: &quot;vue&quot;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>以上是在<code>Vue</code>实例中添加<code>template</code>的情况。</p>
<p>那么这里有一个比较有趣的问题就是，当模板同时放在<code>template</code>参数选项和外部<code>HTML</code>中，会出现什么情况呢？</p>
<p>如下代码所示：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;生命周期2&lt;/title&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;p&gt;你好&lt;/p&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      const vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        template: &quot;&lt;p&gt;Hello &#123;&#123;message&#125;&#125;&lt;/p&gt;&quot;,</span><br><span class="line">        data: &#123;</span><br><span class="line">          message: &quot;vue&quot;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们添加了<code>template</code>属性，同时也在外部添加了模板内容，但是最终在页面上显示的是<code>Hello vue</code> 而不是“你好”。就是因为<code>template</code>参数的优先级比外部<code>HTML</code>的优先级要高。</p>
<p>当然，我们在开发中，基本上都是使用外部的<code>HTML</code>模板形式，因为更加的灵活。</p>
<p>在这里，还需要你再次思考一个问题，就是为什么先判断 <code>el</code> 选项，然后在判断<code>template</code>选项呢？</p>
<p>其实通过上面的总结，我们是可以完全总结出来的。</p>
<p>就是因为<code>Vue</code>需要通过<code>el</code>的“选择器”找到对应的<code>template</code>.也就是说，<code>Vue</code>首先通过<code>el</code>参数去查找对应的<code>template</code>.如果没有找到<code>template</code>参数，则到外部<code>HTML</code>中查找，找到后将模板编译成<code>render</code></p>
<p>函数（<code>Vue</code>的编译实际上就是指<code>Vue</code>把模板编译成<code>render</code>函数的过程）。</p>
<p>下面，我们继续看一下生命周期的流程图。</p>
<p>接下来会触发<code>beforeMount</code>这个钩子函数：</p>
<p>在执行该钩子函数的时候，虚拟<code>DOM</code>已经创建完成，马上就要渲染了，在这里可以更改<code>data</code>中的数据，不会触发<code>updated</code>, 其实在<code>created</code>中也是可以更改数据，也不会触发<code>updated</code>函数</p>
<p>测试代码如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">beforeMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;beforeMount&quot;</span>);</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;beforeMount el===&quot;</span>, <span class="variable language_">this</span>.<span class="property">$el</span>);</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;data==&quot;</span>, <span class="variable language_">this</span>.<span class="property">$data</span>);</span><br><span class="line">        <span class="comment">//this.foo = &quot;abc&quot;; //修改数据</span></span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;foo==&quot;</span>, <span class="variable language_">this</span>.<span class="property">foo</span>);</span><br><span class="line">      &#125;,</span><br></pre></td></tr></table></figure>

<p>通过上面的代码，我们可以获取<code>el</code>中的内容，同时也可以修改数据。</p>
<p>但是，这里需要注意的输入的<code>el</code>中的内容，<code>&#123;&#123;foo&#125;&#125;</code>还没有被真正的数据替换掉。而且对应的内容还没有挂载到页面上。</p>
<p>下面执行了<code>Create VM.$el and replace &quot;el&quot; with it</code></p>
<p>经过这一步后，在模板中所写的<code>&#123;&#123;foo&#125;&#125;</code>会被具体的数据所替换掉。</p>
<p>所以下面执行<code>mounted</code>的时候，可以看到真实的数据。同时整个组件内容已经挂载到页面中了，数据以及真实<code>DOM</code>都已经处理好了，可以在这里操作真实<code>DOM</code>了，也就是在<code>mounted</code>的时候，页面已经被渲染完毕了，在这个钩子函数中，我们可以去发送<code>ajax</code>请求。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;mounted&quot;</span>);</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;mounted el===&quot;</span>, <span class="variable language_">this</span>.<span class="property">$el</span>);</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;data==&quot;</span>, <span class="variable language_">this</span>.<span class="property">$data</span>);</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;foo==&quot;</span>, <span class="variable language_">this</span>.<span class="property">foo</span>);</span><br><span class="line">      &#125;</span><br></pre></td></tr></table></figure>

<p>所以说，最开始的问题中，<code>D</code>选项：<code>DOM渲染在mounted中就已经完成了</code>这句话的描述也是正确的。</p>
<p>下面继续看生命周期的流程，如下图所示：</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/update.png"></p>
<p>当整个组件挂在完成后，有可能会进行数据的修改，当<code>Vue</code>发现<code>data</code>中的数据发生了变化，会触发对应组件的重新渲染，先后调用了<code>beforeUpdate</code> 和<code>updated</code>钩子函数。</p>
<p>在<code>updated</code>之前<code>beoreUpdate</code>之后有一个非常重要的操作就是虚拟<code>DOM</code>会重新构建，也就是新构建的虚拟<code>DOM</code>与上一次的虚拟<code>DOM</code>树利用<code>diff</code>算法进行对比之后重新渲染。</p>
<p>而到了<code>updated</code>这个方法，就表示数据已经更新完成，<code>dom</code>也重新<code>render</code>完成。</p>
<p>下面如果我们调用了<code>vm.$destroy</code>方法后，就会销毁所有的资源。</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/destroyed.png"></p>
<p>首先会执行<code>beforeDestroy</code> 这个钩子函数，这个钩子函数在实例销毁前调用，在这一步，实例仍然可用。</p>
<p>在该方法中，可以做一些清理的工作，例如：清除定时器等。</p>
<p>但是执行到<code>destroyed</code>钩子函数的时候，<code>Vue</code>实例已经被销毁，所有的事件监听器会被移除，所有的子实例也会被销毁。</p>
<p>最后做一个简单的总结：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">beforeCreate( )// 该钩子函数执行时，组件实例还未创建.</span><br><span class="line">created()//组件初始化完毕，各种数据可以使用，可以使用ajax发送异步请求获取数据</span><br><span class="line">beforeMounted()// 未执行渲染，更新，虚拟DOM完成，真实DOM未创建</span><br><span class="line">mounted()// 初始化阶段结束，真实DOM已经创建，可以发送异步请求获取数据,也可以访问dom元素</span><br><span class="line">beforeUpdate()//更新前，可用于获取更新前各种状态数据</span><br><span class="line">updated()//更新后执行该钩子函数，所有的状态数据是最新的。</span><br><span class="line">beforeDestroy() // 销毁前执行，可以用于一些定时器的清除。</span><br><span class="line">destroyed()//组件已经销毁，事件监听器被移除，所有的子实例也会被销毁。</span><br></pre></td></tr></table></figure>

<p>以上为生命周期的内容。</p>
<h2 id="12、组件化应用"><a href="#12、组件化应用" class="headerlink" title="12、组件化应用"></a>12、组件化应用</h2><h3 id="12-1-组件概述"><a href="#12-1-组件概述" class="headerlink" title="12.1 组件概述"></a>12.1 组件概述</h3><p>在这一小节中，重点要理解的就是组件的编程思想。</p>
<p>组件表示页面中的部分功能（包含自己的逻辑与样式），可以组合多个组件实现完整的页面功能。</p>
<p>如下图所示：</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/%E7%BB%84%E4%BB%B6.png"></p>
<p><strong>问题是，如何确定页面中哪些内容划分到一个组件中呢？</strong></p>
<p>但你如何确定应该将哪些部分划分到一个组件中呢？你可以将组件当作一种函数或者是对象来考虑（函数的功能是单一的），根据[<strong>单一功能原则</strong>]来判定组件的范围。也就是说，一个组件原则上只能负责一个功能。如果它需要负责更多的功能，这时候就应该考虑将它拆分成更小的组件。</p>
<p>当然，在上图中，我们发现’Name‘和’Price’ 表头 并没有单独的划分到一个组件中，主要考虑的是功能简单，就是展示的作用，所以没有划分到单独一个组件中。如果，该表头具有了一些比较复杂的功能，例如排序。那么这里可以单独的将表头内容划分到一个组件中。</p>
<p>组件有什么特点呢？</p>
<p>可复用、维护、可组合</p>
<p>可复用：每个组件都是具有独立功能的，它可以被使用在多个场景中。</p>
<p>可组合：一个组件可以和其它的组件一起使用或者可以直接嵌套在另一个组件内部。</p>
<p>可维护：每个组件仅仅包含自身的逻辑，更容易被理解和维护。</p>
<p>下面，看一下怎样创建组件？</p>
<h3 id="12-2-组件的基本使用"><a href="#12-2-组件的基本使用" class="headerlink" title="12.2 组件的基本使用"></a>12.2 组件的基本使用</h3><p>组件具体的创建过程如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;index&quot;</span>, &#123;</span><br><span class="line">  <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;我是首页的组件&lt;/div&gt;&quot;</span>,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>第一个参数指定了所创建的组件的名字，第二个参数指定了模板。</p>
<p>组件创建好以后，具体的使用方式如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">index</span>&gt;</span><span class="tag">&lt;/<span class="name">index</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>注意：1. 模板 template 中只能有一个根节点;2. 组件的名字，如果采用驼峰命令的话，在使用的时候，就要加上 “-”，比如组件名字叫 indexA，那么在使用的时候就叫 index-a。</p>
<p>例如：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;componentA&quot;</span>, &#123;</span><br><span class="line">  <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;创建一个新的组件&lt;/div&gt;&quot;</span>,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>组件的使用</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">component-a</span>&gt;</span><span class="tag">&lt;/<span class="name">component-a</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在 Vue 实例中所使用的选项，在组件中都可以使用<strong>，但是要注意 data,在组件中使用时必须是一个函数。</strong></p>
<p>下面创建一个 about 组件。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;about&quot;</span>, &#123;</span><br><span class="line">  <span class="attr">template</span>: <span class="string">&#x27;&lt;div&gt;&#123;&#123;msg&#125;&#125;&lt;button @click=&quot;showMsg&quot;&gt;单击&lt;/button&gt;&lt;/div&gt;&#x27;</span>,</span><br><span class="line">  <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      <span class="attr">msg</span>: <span class="string">&quot;大家好&quot;</span>,</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="title function_">showMsg</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">msg</span> = <span class="string">&quot;关于组件&quot;</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>组件的使用如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">about</span>&gt;</span><span class="tag">&lt;/<span class="name">about</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在组件中关于 data 不是一个对象，而是一个函数的原因，官方文档有明确的说明</p>
<p><a target="_blank" rel="noopener" href="https://cn.vuejs.org/v2/guide/components.html">https://cn.vuejs.org/v2/guide/components.html</a></p>
<p>组件创建完整的代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;ie=edge&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>组件创建<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">component-a</span>&gt;</span><span class="tag">&lt;/<span class="name">component-a</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">index</span>&gt;</span><span class="tag">&lt;/<span class="name">index</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">index</span>&gt;</span><span class="tag">&lt;/<span class="name">index</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">about</span>&gt;</span><span class="tag">&lt;/<span class="name">about</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;componentA&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;创建一个新的组件&lt;/div&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;index&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;我是首页的组件&lt;/div&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;about&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&#x27;&lt;div&gt;&#123;&#123;msg&#125;&#125;&lt;button @click=&quot;showMsg&quot;&gt;单击&lt;/button&gt;&lt;/div&gt;&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">msg</span>: <span class="string">&quot;大家好&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">showMsg</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">msg</span> = <span class="string">&quot;关于组件&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">var</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在使用组件的时候，需要注意以下几点内容：</p>
<p>第一点：<code>data</code>必须是一个函数</p>
<p>关于这一点，官方文档有比较详细清楚的说明：<code>https://cn.vuejs.org/v2/guide/components.html</code></p>
<p>第二：组件模板中必须有一个跟元素。</p>
<p>第三：组件模板内容可以使用模板字符串。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Vue.component(&quot;about&quot;, &#123; template: `</span><br><span class="line">&lt;div&gt;</span><br><span class="line">                 &#123;&#123;msg&#125;&#125;</span><br><span class="line">                &lt;button @click=&#x27;showMsg&#x27;&gt;单击</span><br><span class="line">                &lt;/button&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">`, data() &#123; return &#123; msg: &quot;大家好&quot;, &#125;; &#125;, methods: &#123; showMsg() &#123; this.msg =</span><br><span class="line">&quot;关于VUE组件&quot;; &#125;, &#125;, &#125;);</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们在组件的模板中使用类模板字符串，这样就可以调整对应的格式，例如换行等。</p>
<p>第四：现在我们创建的组件是全局组件，可以在其它组件中使用。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;组件基本使用&lt;/title&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;index&gt;&lt;/index&gt;</span><br><span class="line">      &lt;component-a&gt;&lt;/component-a&gt;</span><br><span class="line">      &lt;about&gt;&lt;/about&gt;</span><br><span class="line">      &lt;!-- 使用HelloWorld组件 --&gt;</span><br><span class="line">      &lt;hello-world&gt;&lt;/hello-world&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      Vue.component(&quot;index&quot;, &#123;</span><br><span class="line">        template: &quot;&lt;div&gt;我是Index组件&lt;/div&gt;&quot;,</span><br><span class="line">      &#125;);</span><br><span class="line">      //   创建了HelloWorld组件</span><br><span class="line">      Vue.component(&quot;HelloWorld&quot;, &#123;</span><br><span class="line">        data() &#123;</span><br><span class="line">          return &#123;</span><br><span class="line">            msg: &quot;Hello World&quot;,</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;,</span><br><span class="line">        template: &quot;&lt;div&gt;&#123;&#123; msg&#125;&#125;&lt;/div&gt;&quot;,</span><br><span class="line">      &#125;);</span><br><span class="line">      //   使用HelloWorld组件</span><br><span class="line">      Vue.component(&quot;componentA&quot;, &#123;</span><br><span class="line">        template: &quot;&lt;div&gt;我是一个新的组件:&lt;HelloWorld&gt;&lt;/HelloWorld&gt;&lt;/div&gt;&quot;,</span><br><span class="line">      &#125;);</span><br><span class="line"></span><br><span class="line">      Vue.component(&quot;about&quot;, &#123;</span><br><span class="line">        template: `&lt;div&gt;</span><br><span class="line">                 &#123;&#123;msg&#125;&#125;</span><br><span class="line">                &lt;button @click=&#x27;showMsg&#x27;&gt;单击</span><br><span class="line">                &lt;/button&gt;</span><br><span class="line">            &lt;/div&gt;`,</span><br><span class="line">        data() &#123;</span><br><span class="line">          return &#123;</span><br><span class="line">            msg: &quot;大家好&quot;,</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;,</span><br><span class="line">        methods: &#123;</span><br><span class="line">          showMsg() &#123;</span><br><span class="line">            this.msg = &quot;关于VUE组件&quot;;</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">      const vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;&#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们又创建了一个<code>HelloWorld</code>组件，并且在<code>componentA</code>组件中去使用了<code>HelloWorld</code>组件，这里还需要注意的一点就是，在<code>componentA</code>这个组件中使用<code>HelloWorld</code>这个组件的时候，可以使用驼峰命名的方式，但是在<code>&lt;div id=&quot;app&quot;&gt;&lt;/div&gt;</code>这个普通的标签模板中，必须使用短横线的方式，才能使用组件。</p>
<h3 id="12-3-局部组件注册"><a href="#12-3-局部组件注册" class="headerlink" title="12.3 局部组件注册"></a>12.3 局部组件注册</h3><p>我们可以在一个组件中，再次注册另外一个组件，这样就构成了父子关系。</p>
<p>可以通过 components 来创建对应的子组件。</p>
<p>组件的创建过程如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">Vue.component(&quot;father&quot;, &#123;</span><br><span class="line">  template: &quot;&lt;div&gt;&lt;p&gt;我是父组件&lt;/p&gt;&lt;son&gt;&lt;/son&gt;&lt;/div&gt;&quot;,</span><br><span class="line">  components: &#123;</span><br><span class="line">    // 创建一个子组件</span><br><span class="line">    son: &#123;</span><br><span class="line">      template: &quot;&lt;p&gt;我是子组件&lt;/p&gt;&quot;,</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br><span class="line">var vm = new Vue(&#123;</span><br><span class="line">  el: &quot;#app&quot;,</span><br><span class="line">  data: &#123;&#125;,</span><br><span class="line">&#125;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p>组件的使用</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">father</span>&gt;</span><span class="tag">&lt;/<span class="name">father</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>完整代码如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;ie=edge&quot; /&gt;</span><br><span class="line">    &lt;title&gt;父子组件创建&lt;/title&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line"></span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;father&gt;&lt;/father&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      Vue.component(&quot;father&quot;, &#123;</span><br><span class="line">        template: &quot;&lt;div&gt;&lt;p&gt;我是父组件&lt;/p&gt;&lt;son&gt;&lt;/son&gt;&lt;/div&gt;&quot;,</span><br><span class="line">        components: &#123;</span><br><span class="line">          // 创建一个子组件</span><br><span class="line">          son: &#123;</span><br><span class="line">            template: &quot;&lt;p&gt;我是子组件&lt;/p&gt;&quot;,</span><br><span class="line">          &#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">      var vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;&#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们是在全局的<code>father</code>组件中，又创建了一个子组件<code>son</code>.</p>
<p>那么<code>son</code>这个子组件也就是一个局部的组件。也就是它只能在<code>father</code>组件中使用。</p>
<p>当然，我们在<code>father</code>中定义子组件<code>son</code>的时候，直接在其内部构件模板内容，这样如果代码非常多的时候，就不是很直观。</p>
<p>所以这里，我们可以将<code>son</code>组件，单独的进行定义，然后在<code>father</code>组件中进行注册。</p>
<p>改造后的代码如下所示：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;局部组件&lt;/title&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;father&gt;&lt;/father&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      const son = &#123;</span><br><span class="line">        data() &#123;</span><br><span class="line">          return &#123;</span><br><span class="line">            msg: &quot;Hello 我是子组件&quot;,</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;,</span><br><span class="line">        template: `&lt;div&gt;&#123;&#123;msg&#125;&#125;&lt;/div&gt;`,</span><br><span class="line">      &#125;;</span><br><span class="line">      Vue.component(&quot;father&quot;, &#123;</span><br><span class="line">        template: &quot;&lt;div&gt;&lt;p&gt;我是父组件&lt;/p&gt;&lt;son&gt;&lt;/son&gt;&lt;/div&gt;&quot;,</span><br><span class="line">        components: &#123;</span><br><span class="line">          // 创建一个子组件</span><br><span class="line">          //   son: &#123;</span><br><span class="line">          //     template: &quot;&lt;p&gt;我是子组件&lt;/p&gt;&quot;,</span><br><span class="line">          //   &#125;,</span><br><span class="line">          son: son,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">      var vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;&#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们将<code>son</code>组件单独的进行了定义，这时注意写法，是一个对象的格式，在对象中包含了关于组件很重要的内容为<code>data</code>函数与<code>template</code>属性。</p>
<p>同时在<code>father</code>组件中通过<code>components</code>属性完成了对<code>son</code>组件的注册。</p>
<p>我们说过<code>son</code>组件是一个局部的组件，那么只能在其注册的父组件中使用。</p>
<p>现在，我们可以测试一下：</p>
<p>完整代码如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;局部组件&lt;/title&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;father&gt;&lt;/father&gt;</span><br><span class="line">      &lt;!-- 使用ComponentA组件 --&gt;</span><br><span class="line">      &lt;component-a&gt;&lt;/component-a&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      const son = &#123;</span><br><span class="line">        data() &#123;</span><br><span class="line">          return &#123;</span><br><span class="line">            msg: &quot;Hello 我是子组件&quot;,</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;,</span><br><span class="line">        template: `&lt;div&gt;&#123;&#123;msg&#125;&#125;&lt;/div&gt;`,</span><br><span class="line">      &#125;;</span><br><span class="line">      //定义ComponentA组件</span><br><span class="line">      Vue.component(&quot;ComponentA&quot;, &#123;</span><br><span class="line">        template: &quot;&lt;div&gt;&lt;son&gt;&lt;/son&gt;&lt;/div&gt;&quot;,</span><br><span class="line">      &#125;);</span><br><span class="line">      Vue.component(&quot;father&quot;, &#123;</span><br><span class="line">        template: &quot;&lt;div&gt;&lt;p&gt;我是父组件&lt;/p&gt;&lt;son&gt;&lt;/son&gt;&lt;/div&gt;&quot;,</span><br><span class="line">        components: &#123;</span><br><span class="line">          // 创建一个子组件</span><br><span class="line">          //   son: &#123;</span><br><span class="line">          //     template: &quot;&lt;p&gt;我是子组件&lt;/p&gt;&quot;,</span><br><span class="line">          //   &#125;,</span><br><span class="line">          son: son,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">      var vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;&#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们又创建了一个全局的组件<code>ComponentA</code>,并且在该组件中使用了<code>son</code>组件，注意这里没有在<code>ComponentA</code>中使用<code>components</code>来注册<code>son</code>组件，而是直接使用。同时在<code>&lt;div id=&#39;app&#39;&gt;&lt;/div&gt;</code>中使用了<code>ComponentA</code>组件。这时在浏览器中，打开上面的程序，会出现错误。</p>
<p>如果现在就想在<code>ComponentA</code>组件中使用<code>son</code>组件，就需要使用<code>components</code>来注册。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;ComponentA&quot;</span>, &#123;</span><br><span class="line">  <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;&lt;son&gt;&lt;/son&gt;&lt;/div&gt;&quot;</span>,</span><br><span class="line">  <span class="attr">components</span>: &#123;</span><br><span class="line">    <span class="attr">son</span>: son,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>现在在<code>ComponentA</code>组件中已经注册了<code>son</code>组件，这时刷新浏览器就不会出错了。</p>
<p>在上面这些案例中，我们是在一个全局的组件中注册一个局部的组件，其实，我们也可以在<code>Vue</code>实例中，</p>
<p>注册对应的局部组件。因为，我们也可以将<code>vue</code>实例作为一个组件。</p>
<p>详细代码如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;局部组件&lt;/title&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;father&gt;&lt;/father&gt;</span><br><span class="line">      &lt;component-a&gt;&lt;/component-a&gt;</span><br><span class="line">      &lt;hello-msg&gt;&lt;/hello-msg&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      const son = &#123;</span><br><span class="line">        data() &#123;</span><br><span class="line">          return &#123;</span><br><span class="line">            msg: &quot;Hello 我是子组件&quot;,</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;,</span><br><span class="line">        template: `&lt;div&gt;&#123;&#123;msg&#125;&#125;&lt;/div&gt;`,</span><br><span class="line">      &#125;;</span><br><span class="line">      // 定义HelloMsg组件</span><br><span class="line">      const HelloMsg = &#123;</span><br><span class="line">        data() &#123;</span><br><span class="line">          return &#123;</span><br><span class="line">            msg: &quot;Hello World&quot;,</span><br><span class="line">          &#125;;</span><br><span class="line">        &#125;,</span><br><span class="line">        template: `&lt;div&gt;&#123;&#123;msg&#125;&#125;&lt;/div&gt;`,</span><br><span class="line">      &#125;;</span><br><span class="line">      Vue.component(&quot;ComponentA&quot;, &#123;</span><br><span class="line">        template: &quot;&lt;div&gt;&lt;son&gt;&lt;/son&gt;&lt;/div&gt;&quot;,</span><br><span class="line">        components: &#123;</span><br><span class="line">          son: son,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">      Vue.component(&quot;father&quot;, &#123;</span><br><span class="line">        template: &quot;&lt;div&gt;&lt;p&gt;我是父组件&lt;/p&gt;&lt;son&gt;&lt;/son&gt;&lt;/div&gt;&quot;,</span><br><span class="line">        components: &#123;</span><br><span class="line">          // 创建一个子组件</span><br><span class="line">          //   son: &#123;</span><br><span class="line">          //     template: &quot;&lt;p&gt;我是子组件&lt;/p&gt;&quot;,</span><br><span class="line">          //   &#125;,</span><br><span class="line">          son: son,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">      var vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;&#125;,</span><br><span class="line">        components: &#123;</span><br><span class="line">          &quot;hello-msg&quot;: HelloMsg,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们又创建了一个组件<code>HelloMsg</code></p>
<p>然后将<code>HelloMsg</code>组件注册到了 <code>Vue</code>实例中，注意：在进行注册的时候的语法格式。</p>
<p>左侧为组件的名称，由于这个组件创建的时候采用的是驼峰命名的方式，所以组件的名称采用短横线的方式。</p>
<p>右侧为组件的内容。</p>
<p>下面就可以在其<code>&lt;div id=&quot;app&quot;&gt;&lt;/div&gt;</code>中使用了。</p>
<p>同理，在其他的组件中是无法使用<code>HelloMsg</code>组件的。</p>
<h2 id="13、组件通信"><a href="#13、组件通信" class="headerlink" title="13、组件通信"></a>13、组件通信</h2><h3 id="13-1-父组件向子组件传值"><a href="#13-1-父组件向子组件传值" class="headerlink" title="13.1 父组件向子组件传值"></a>13.1 父组件向子组件传值</h3><p>当我们将整个页面都拆分了不同的组件以后，这样就会涉及到组件之间的数据传递问题。</p>
<p>常见的组件的通信可以分为三类：</p>
<p>第一类: 父组件向子组件传递数据</p>
<p>第二类: 子组件向父组件传递数据</p>
<p>第三类：兄弟组件的数据传递。</p>
<p>下面，我们先来看一下父组件向子组件传递数据的情况</p>
<p>第一：子组件内部通过<code>props</code>接收传递过来的值。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&#x27;menu-item&#x27;</span>,&#123;</span><br><span class="line"> <span class="attr">props</span>:[<span class="string">&#x27;title&#x27;</span>] <span class="comment">// props后面跟一个数组，数组中的内容为字符串，这个字符串可以当做属性类使用。</span></span><br><span class="line"> <span class="attr">template</span>:<span class="string">&#x27;&lt;div&gt;&#123;&#123;title&#125;&#125;&lt;/div&gt;&#x27;</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>第二: 父组件通过属性将值传递给子组件</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">menu-item</span> <span class="attr">title</span>=<span class="string">&quot;向子组件传递数据&quot;</span>&gt;</span> <span class="tag">&lt;/<span class="name">menu-item</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">menu-item</span> <span class="attr">:title</span>=<span class="string">&quot;title&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">menu-item</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--可以使用动态绑定的方式来传值--&gt;</span></span><br></pre></td></tr></table></figure>

<p>下面看一下具体的案例演示：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">father</span>&gt;</span><span class="tag">&lt;/<span class="name">father</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="comment">// 创建一个父组件</span></span></span><br><span class="line"><span class="language-javascript">    <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;father&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 2、在使用子组件的地方，通过v-bind指令来给子组件中的props赋值。</span></span></span><br><span class="line"><span class="language-javascript">      <span class="attr">template</span>: <span class="string">&#x27;&lt;div&gt;&lt;p&gt;我是父组件&lt;/p&gt;&lt;son :myName=&quot;mySonName&quot;&gt;&lt;/son&gt;&lt;/div&gt;&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">      <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">mySonName</span>: <span class="string">&quot;小强&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;;</span></span><br><span class="line"><span class="language-javascript">      &#125;,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">components</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 创建一个子组件</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 1.声明props,它的作用是：用来接收父组件传递过来的数据。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// props可以跟一个数组，数组里面的内容可以是字符串，这个字符串可以当属性来使用。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">son</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">props</span>: [<span class="string">&quot;myName&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">template</span>: <span class="string">&quot;&lt;p&gt;我是子组件,我的名字叫&#123;&#123;myName&#125;&#125;&lt;/p&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;,</span></span><br><span class="line"><span class="language-javascript">    &#125;);</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">var</span> vm = <span class="keyword">new</span> <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">    &#125;)();</span></span><br><span class="line"><span class="language-javascript">  </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>下面我们在看一个例子，这个例子是前面我们写的关于局部组件的案例，我们在这个案例的基础上实现组件的传值。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>局部组件<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">father</span>&gt;</span><span class="tag">&lt;/<span class="name">father</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">component-a</span>&gt;</span><span class="tag">&lt;/<span class="name">component-a</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">hello-msg</span> <span class="attr">title</span>=<span class="string">&quot;你好&quot;</span> <span class="attr">:pcontent</span>=<span class="string">&quot;content&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">hello-msg</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> son = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">msg</span>: <span class="string">&quot;Hello 我是子组件&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`&lt;div&gt;&#123;&#123;msg&#125;&#125;&lt;/div&gt;`</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 定义HelloMsg组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> <span class="title class_">HelloMsg</span> = &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;title&quot;</span>, <span class="string">&quot;pcontent&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">msg</span>: <span class="string">&quot;Hello World&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`&lt;div&gt;&#123;&#123;msg+&#x27;----------&#x27;+title+&#x27;-----------&#x27;+pcontent&#125;&#125;&lt;/div&gt;`</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;;</span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;ComponentA&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;&lt;son&gt;&lt;/son&gt;&lt;/div&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">components</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">son</span>: son,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;father&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;&lt;p&gt;我是父组件&lt;/p&gt;&lt;son&gt;&lt;/son&gt;&lt;/div&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">components</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">// 创建一个子组件</span></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//   son: &#123;</span></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//     template: &quot;&lt;p&gt;我是子组件&lt;/p&gt;&quot;,</span></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//   &#125;,</span></span></span><br><span class="line"><span class="language-javascript">          <span class="attr">son</span>: son,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">var</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">content</span>: <span class="string">&quot;来自父组件中的内容&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">components</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="string">&quot;hello-msg&quot;</span>: <span class="title class_">HelloMsg</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们首先给<code>hello-msg</code> 这个组件传递了一个属性<code>title</code>,该属性的值是固定的。在对应的<code>HelloMsg</code>组件内容定义<code>props</code>,来接收传递过来的<code>title</code>属性的值。然后在<code>template</code>模板中展示<code>title</code>的值。</p>
<p>接下来，又在<code>vue</code>实例中指定了一个<code>content</code>的属性，下面要将该属性的值传递给<code>HelloMsg</code>组件。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">hello-msg</span> <span class="attr">title</span>=<span class="string">&quot;你好&quot;</span> <span class="attr">:pcontent</span>=<span class="string">&quot;content&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">hello-msg</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>这里需要动态绑定的方式将<code>content</code>的值传递到<code>HelloMsg</code>组件。这里动态绑定的属性为<code>pcontent</code>,所以在<code>HelloMsg</code>组件内部，需要在<code>props</code>的数组中添加一个<code>pcontent</code>,最后在<code>template</code>模板中展示出<code>pcontent</code>的内容。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 定义HelloMsg组件</span></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">HelloMsg</span> = &#123;</span><br><span class="line">  <span class="attr">props</span>: [<span class="string">&quot;title&quot;</span>, <span class="string">&quot;pcontent&quot;</span>],</span><br><span class="line">  <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      <span class="attr">msg</span>: <span class="string">&quot;Hello World&quot;</span>,</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`&lt;div&gt;&#123;&#123;msg+&#x27;----------&#x27;+title+&#x27;-----------&#x27;+pcontent&#125;&#125;&lt;/div&gt;`</span>,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>通过上面的案例，我们可以看到，在子组件中可以使用<code>props</code>来接收父组件中传递过来的数据。</p>
<p>但是，<code>props</code>在进行命名的时候，也是有一定的规则的。</p>
<p>如果在<code>props</code>中使用驼峰形式，模板中需要短横线的形式，如下代码案例所示：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Vue.component(&#x27;menu-item&#x27;,&#123; //在JavaScript中是驼峰形式 props:[&#x27;menuTitle&#x27;],</span><br><span class="line">template:&#x27;</span><br><span class="line">&lt;div&gt;&#123;&#123;menuTitle&#125;&#125;&lt;/div&gt;</span><br><span class="line">&#x27; &#125;)</span><br><span class="line">&lt;!--在html中是短横线方式---&gt;</span><br><span class="line">&lt;menu-item menu-title=&quot;hello world&quot;&gt;&lt;/menu-item&gt;</span><br></pre></td></tr></table></figure>

<p>下面看一下具体的代码演示：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>组件传值<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">menu-item</span> <span class="attr">:menu-title</span>=<span class="string">&quot;ptitle&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">menu-item</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;menu-item&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;menuTitle&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`&lt;div&gt;来自&#123;&#123;menuTitle&#125;&#125;&lt;/div&gt;`</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">ptitle</span>: <span class="string">&quot;父组件中的数据&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>下面再来看一下<code>props</code>属性值的类型。</p>
<p><code>props</code> 可以接收各种类型的值。</p>
<p>如下：</p>
<p>字符串（<code>String</code>）</p>
<p>数值(<code>Number</code>)</p>
<p>布尔值(<code>Boolean</code>)</p>
<p>数组(<code>Array</code>)</p>
<p>对象(<code>Object</code>)</p>
<p>下面，将上面的类型都演示一下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>props类型<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">menu-item</span></span></span><br><span class="line"><span class="tag">        <span class="attr">:str</span>=<span class="string">&quot;str&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">:num</span>=<span class="string">&quot;10&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">b</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">:marr</span>=<span class="string">&quot;arr&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">:obj</span>=<span class="string">&quot;obj&quot;</span></span></span><br><span class="line"><span class="tag">      &gt;</span><span class="tag">&lt;/<span class="name">menu-item</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      Vue.component(&quot;menu-item&quot;, &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        props: [&quot;str&quot;, &quot;num&quot;, &quot;b&quot;, &quot;marr&quot;, &quot;obj&quot;],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">str</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">typeof</span> num&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">typeof</span> b&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                   <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;<span class="name">li</span> <span class="attr">:key</span>=<span class="string">item.id</span> <span class="attr">v-for</span>=<span class="string">&#x27;item in marr&#x27;</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.userName</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                   <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">               <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">               <span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                姓名： </span><span class="template-variable">&#123;&#123;<span class="name">obj.name</span>&#125;&#125;</span><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                年龄:</span><span class="template-variable">&#123;&#123;<span class="name">obj.age</span>&#125;&#125;</span><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          str: &quot;hello&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          arr: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123; id: 1, userName: &quot;zhangsan&quot; &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 2,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;lisi&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          obj: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            name: &quot;wangwu&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            age: 18,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，向<code>menu-item</code>组件中传递了各种类型的数据。</p>
<p>注意：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">menu-item</span> <span class="attr">:str</span>=<span class="string">&quot;str&quot;</span> <span class="attr">:num</span>=<span class="string">&quot;10&quot;</span> <span class="attr">b</span>=<span class="string">&quot;true&quot;</span> <span class="attr">:marr</span>=<span class="string">&quot;arr&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">menu-item</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，<code>:num=&quot;10&quot;</code>表示传递的是数字，如果写成<code>num=&#39;10&#39;</code> 表示传递的是字符，</p>
<p>同理<code>b=&quot;true&quot;</code>传递的是字符，如果修改成<code>:b=true</code>表示传递的是布尔类型。</p>
<p>最后还传递了数组类型与对象类型的内容。</p>
<h3 id="13-2-子组件向父组件传值"><a href="#13-2-子组件向父组件传值" class="headerlink" title="13.2 子组件向父组件传值"></a>13.2 子组件向父组件传值</h3><p>第一：子组件通过自定义事件向父组件传递信息。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;button v-on:click=&#x27;$emit(&quot;countSum&quot;)&#x27;&gt; 计算&lt;/button&gt;</span><br></pre></td></tr></table></figure>

<p>第二：父组件监听子组件的事件</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;menu-item v-on:countSum=&#x27;sum+=1&#x27;&gt;&lt;/menu-item&gt;</span><br></pre></td></tr></table></figure>

<p>具体的实现步骤如下：</p>
<p>1、构建基本的结构</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">&lt;div id=<span class="string">&quot;app&quot;</span>&gt;&lt;/div&gt;;</span><br><span class="line"><span class="keyword">var</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">  <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span><br><span class="line">  <span class="attr">data</span>: &#123;&#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>2、构建相应的父组件。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&#x27;father&#x27;</span>, &#123;</span><br><span class="line">          <span class="attr">template</span>: <span class="string">&#x27;&lt;div&gt;我的儿子叫&#123;&#123;mySonName&#125;&#125;&lt;/div&gt;&#x27;</span>,</span><br><span class="line">          <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">              <span class="keyword">return</span> &#123;</span><br><span class="line">                  <span class="attr">mySonName</span>: <span class="string">&#x27;&#x27;</span></span><br><span class="line">              &#125;</span><br><span class="line">          &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>3、 构建相应的子组件, 并且单击子组件中的按钮给父组件传值。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&#x27;father&#x27;</span>, &#123;</span><br><span class="line">          <span class="attr">template</span>: <span class="string">&#x27;&lt;div&gt;我的儿子叫&#123;&#123;mySonName&#125;&#125;&lt;/div&gt;&#x27;</span>,</span><br><span class="line">          <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">              <span class="keyword">return</span> &#123;</span><br><span class="line">                  <span class="attr">mySonName</span>: <span class="string">&#x27;&#x27;</span></span><br><span class="line">              &#125;</span><br><span class="line">          &#125;,</span><br><span class="line">      <span class="attr">components</span>: &#123;</span><br><span class="line">              <span class="attr">son</span>: &#123;</span><br><span class="line">                  <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">                      <span class="keyword">return</span> &#123;</span><br><span class="line">                          <span class="attr">myName</span>: <span class="string">&#x27;小强&#x27;</span></span><br><span class="line">                      &#125;</span><br><span class="line">                  &#125;,</span><br><span class="line">                  <span class="attr">template</span>: <span class="string">&#x27;&lt;button @click=&quot;emitMyName&quot;&gt;我叫&#123;&#123;myName&#125;&#125;&lt;/button&gt;&#x27;</span>,</span><br><span class="line">                  <span class="attr">methods</span>: &#123;</span><br><span class="line">                      <span class="title function_">emitMyName</span>(<span class="params"></span>) &#123;</span><br><span class="line">                          <span class="comment">// 子组件传值给父组件需要用到$emit()方法，这个方法可以传递两个参数，一个是事件名称，一个是需要传递的数据</span></span><br><span class="line">                          <span class="variable language_">this</span>.$emit(<span class="string">&#x27;tellMyFatherMyName&#x27;</span>, <span class="variable language_">this</span>.<span class="property">myName</span>)</span><br><span class="line">                      &#125;</span><br><span class="line">                  &#125;</span><br><span class="line">              &#125;</span><br><span class="line">          &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>4、父组件接收子组件传递过来的数据。</p>
<p>注意在父组件中引用子组件，同时指定在子组件中定义的事件。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&#x27;father&#x27;</span>, &#123;</span><br><span class="line">         <span class="attr">template</span>: <span class="string">&#x27;&lt;div&gt;我的儿子叫&#123;&#123;mySonName&#125;&#125;&lt;son @tellMyFatherMyName=&quot;getMySonName&quot;&gt;&lt;/son&gt;&lt;/div&gt;&#x27;</span>,</span><br><span class="line">         <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">             <span class="keyword">return</span> &#123;</span><br><span class="line">                 <span class="attr">mySonName</span>: <span class="string">&#x27;&#x27;</span></span><br><span class="line">             &#125;</span><br><span class="line">         &#125;,</span><br><span class="line">         <span class="attr">methods</span>: &#123;</span><br><span class="line">             <span class="title function_">getMySonName</span>(<span class="params">data</span>) &#123;</span><br><span class="line">                 <span class="variable language_">this</span>.<span class="property">mySonName</span> = data;</span><br><span class="line">             &#125;</span><br><span class="line">         &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>5、组件使用</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">father</span>&gt;</span><span class="tag">&lt;/<span class="name">father</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>6、完整代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">father</span>&gt;</span><span class="tag">&lt;/<span class="name">father</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;father&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">template</span>:</span></span><br><span class="line"><span class="language-javascript">        <span class="string">&#x27;&lt;div&gt;我的儿子叫&#123;&#123;mySonName&#125;&#125;&lt;son @tellMyFatherMyName=&quot;getMySonName&quot;&gt;&lt;/son&gt;&lt;/div&gt;&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">      <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">mySonName</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;;</span></span><br><span class="line"><span class="language-javascript">      &#125;,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">getMySonName</span>(<span class="params">data</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">mySonName</span> = data;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">components</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">son</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">myName</span>: <span class="string">&quot;小强&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">            &#125;;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">template</span>: <span class="string">&#x27;&lt;button @click=&quot;emitMyName&quot;&gt;我叫&#123;&#123;myName&#125;&#125;&lt;/button&gt;&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="title function_">emitMyName</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">// 子组件传值给父组件需要用到$emit()方法，这个方法可以传递两个参数，一个是事件名称，一个是需要传递的数据</span></span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.$emit(<span class="string">&quot;tellMyFatherMyName&quot;</span>, <span class="variable language_">this</span>.<span class="property">myName</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;,</span></span><br><span class="line"><span class="language-javascript">    &#125;);</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">var</span> vm = <span class="keyword">new</span> <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">    &#125;)();</span></span><br><span class="line"><span class="language-javascript">  </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="13-3-兄弟组件之间数据传递"><a href="#13-3-兄弟组件之间数据传递" class="headerlink" title="13.3 兄弟组件之间数据传递"></a>13.3 兄弟组件之间数据传递</h3><p>兄弟组件传值，通过事件总线完成。</p>
<p>1、定义父组件并且在父组件中，完成两个兄弟组件的创建。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&#x27;father&#x27;</span>, &#123;</span><br><span class="line">          <span class="attr">template</span>: <span class="string">&#x27;&lt;div&gt;&lt;son&gt;&lt;/son&gt;&lt;daughter&gt;&lt;/daughter&gt;&lt;/div&gt;&#x27;</span>,</span><br><span class="line">          <span class="attr">components</span>: &#123;</span><br><span class="line">              <span class="attr">son</span>: &#123;</span><br><span class="line">                  <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">                      <span class="keyword">return</span> &#123;</span><br><span class="line">                          <span class="attr">mySisterName</span>: <span class="string">&#x27;&#x27;</span></span><br><span class="line">                      &#125;</span><br><span class="line">                  &#125;,</span><br><span class="line">                  <span class="attr">template</span>: <span class="string">&#x27;&lt;div&gt;我妹妹叫&#123;&#123;mySisterName&#125;&#125;&lt;/div&gt;&#x27;</span></span><br><span class="line">              &#125;,</span><br><span class="line">              <span class="attr">daughter</span>: &#123;</span><br><span class="line">                  <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">                      <span class="keyword">return</span> &#123;</span><br><span class="line">                          <span class="attr">myName</span>: <span class="string">&#x27;小雪&#x27;</span></span><br><span class="line">                      &#125;</span><br><span class="line">                  &#125;,</span><br><span class="line">                  <span class="attr">template</span>: <span class="string">&#x27;&lt;button @click=&quot;emitMyName&quot;&gt;告诉哥哥我叫&#123;&#123;myName&#125;&#125;&lt;/button&gt;&#x27;</span>,</span><br><span class="line">                  <span class="attr">methods</span>: &#123;</span><br><span class="line">                      <span class="title function_">emitMyName</span>(<span class="params"></span>) &#123;</span><br><span class="line"></span><br><span class="line">                      &#125;</span><br><span class="line">                  &#125;</span><br><span class="line">              &#125;</span><br><span class="line">          &#125;</span><br><span class="line">      &#125;)</span><br><span class="line">      <span class="keyword">var</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">          <span class="attr">el</span>: <span class="string">&#x27;#app&#x27;</span>,</span><br><span class="line">          <span class="attr">data</span>: &#123;</span><br><span class="line"></span><br><span class="line">          &#125;</span><br><span class="line">      &#125;)</span><br><span class="line">  &lt;/script&gt;</span><br></pre></td></tr></table></figure>

<p>2、创建事件总线</p>
<p>通过事件总线发射一个事件名称和需要传递的数据 。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 创建一个空的vue实例，作为事件总线</span></span><br><span class="line">      <span class="keyword">var</span> eventbus = <span class="keyword">new</span> <span class="title class_">Vue</span>()</span><br><span class="line">        <span class="attr">daughter</span>: &#123;</span><br><span class="line">                  <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">                      <span class="keyword">return</span> &#123;</span><br><span class="line">                          <span class="attr">myName</span>: <span class="string">&#x27;小雪&#x27;</span></span><br><span class="line">                      &#125;</span><br><span class="line">                  &#125;,</span><br><span class="line">                  <span class="attr">template</span>: <span class="string">&#x27;&lt;button @click=&quot;emitMyName&quot;&gt;告诉哥哥我叫&#123;&#123;myName&#125;&#125;&lt;/button&gt;&#x27;</span>,</span><br><span class="line">                  <span class="attr">methods</span>: &#123;</span><br><span class="line">                      <span class="title function_">emitMyName</span>(<span class="params"></span>) &#123;</span><br><span class="line">                          <span class="comment">// 通过事件总线发射一个事件名称和需要传递的数据</span></span><br><span class="line">                          eventbus.$emit(<span class="string">&#x27;tellBroMyName&#x27;</span>, <span class="variable language_">this</span>.<span class="property">myName</span>)</span><br><span class="line">                      &#125;</span><br><span class="line">                  &#125;</span><br><span class="line">              &#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>3、通过 eventbus 的$on()方法去监听兄弟节点发射过来的事件</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">son</span>: &#123;</span><br><span class="line">                   <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">                       <span class="keyword">return</span> &#123;</span><br><span class="line">                           <span class="attr">mySisterName</span>: <span class="string">&#x27;&#x27;</span></span><br><span class="line">                       &#125;</span><br><span class="line">                   &#125;,</span><br><span class="line">                   <span class="attr">template</span>: <span class="string">&#x27;&lt;div&gt;我妹妹叫&#123;&#123;mySisterName&#125;&#125;&lt;/div&gt;&#x27;</span>,</span><br><span class="line">                   <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span><br><span class="line">                       <span class="comment">// 通过eventbus的$on()方法去监听兄弟节点发射过来的事件</span></span><br><span class="line">                       <span class="comment">// $on有两个参数，一个是事件名称，一个是函数，该函数的默认值就是传递过来的数据</span></span><br><span class="line">                       eventbus.$on(<span class="string">&#x27;tellBroMyName&#x27;</span>, <span class="function"><span class="params">data</span> =&gt;</span> &#123;</span><br><span class="line">                           <span class="variable language_">this</span>.<span class="property">mySisterName</span> = data</span><br><span class="line">                       &#125;)</span><br><span class="line">                   &#125;</span><br><span class="line">               &#125;,</span><br></pre></td></tr></table></figure>

<p>4、组件的使用</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">father</span>&gt;</span><span class="tag">&lt;/<span class="name">father</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>5、完整的代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">father</span>&gt;</span><span class="tag">&lt;/<span class="name">father</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">    <span class="comment">// 创建一个空的vue实例，作为事件总线</span></span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">var</span> eventbus = <span class="keyword">new</span> <span class="title class_">Vue</span>();</span></span><br><span class="line"><span class="language-javascript">    <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;father&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;&lt;son&gt;&lt;/son&gt;&lt;daughter&gt;&lt;/daughter&gt;&lt;/div&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">components</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">son</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">mySisterName</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">            &#125;;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">template</span>: <span class="string">&quot;&lt;div&gt;我妹妹叫&#123;&#123;mySisterName&#125;&#125;&lt;/div&gt;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// 通过eventbus的$on()方法去监听兄弟节点发射过来的事件</span></span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// $on有两个参数，一个是事件名称，一个是函数，该函数的默认值就是传递过来的数据</span></span></span><br><span class="line"><span class="language-javascript">            eventbus.$on(<span class="string">&quot;tellBroMyName&quot;</span>, <span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">mySisterName</span> = data;</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">daughter</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">myName</span>: <span class="string">&quot;小雪&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">            &#125;;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">template</span>:</span></span><br><span class="line"><span class="language-javascript">            <span class="string">&#x27;&lt;button @click=&quot;emitMyName&quot;&gt;告诉哥哥我叫&#123;&#123;myName&#125;&#125;&lt;/button&gt;&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="title function_">emitMyName</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">// 通过事件总线发射一个事件名称和需要传递的数据</span></span></span><br><span class="line"><span class="language-javascript">              eventbus.$emit(<span class="string">&quot;tellBroMyName&quot;</span>, <span class="variable language_">this</span>.<span class="property">myName</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;,</span></span><br><span class="line"><span class="language-javascript">    &#125;);</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">var</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">    &#125;);</span></span><br><span class="line"><span class="language-javascript">  </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="14、组件插槽应用"><a href="#14、组件插槽应用" class="headerlink" title="14、组件插槽应用"></a>14、组件插槽应用</h2><h3 id="14-1-插槽基本使用"><a href="#14-1-插槽基本使用" class="headerlink" title="14.1 插槽基本使用"></a>14.1 插槽基本使用</h3><p><strong>生活中的插槽</strong></p>
<p>其实我们生活中有很多很多的插槽。比如电脑的<code>USB</code>插槽、插板中的电源插槽等等。每个插槽都有它们之间的价值。比如电脑的<code>USB</code>插槽，可以用来插 U 盘，链接鼠标，链接手机、音响等等，通过这些插槽，大大拓展了原有设备的功能。</p>
<p><strong>组件中的插槽</strong></p>
<p>组件中的插槽，<strong>让使用者可以决定组件内部的一些内容到底展示什么</strong>，也就是，插槽可以实现父组件向子组件传递模板内容。具有插槽的组件将会有更加强大的拓展性，</p>
<p>下面看一个实际应用的例子来体会一下插槽的引用场景。</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/%E6%8F%92%E6%A7%BD.jpg"></p>
<p>三个页面中都有导航栏，基本结构都是一样的：左中右分别有一个东西，只是显示的内容不同而已。那我们如何来实现这种<strong>结构相似但是内容不同</strong>呢？<br>  你一定是想着，直接定义三个组件，然后在模板中分别显示不同的内容，对不对？恭喜你，你就快要被炒了。<br>  首先，如果我们封装成三个组件，显然不合适，比如每个页面都有返回，这部分的内容我们就要重复去封装<br>  其次，如果我们封装成一个，还是不合理，因为有些左侧是菜单栏，有些中间是搜索框，有些是文字。<br>那我们该怎么办呢？其实很简单，用组件插槽。</p>
<p>上面最佳的解决办法是<strong>将共性抽取到组件中，将不同暴露给插槽</strong>，一旦我们<strong>使用了插槽，就相当于预留了空间</strong>，<strong>空间的内容取决于使用者</strong></p>
<p>如下图所示：</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/%E6%8F%92%E6%A7%BD1.png"></p>
<p>通过上图，我们可以在父组件中使用子组件，同时由于在子组件中创建插槽<code>slot</code>，也就是相当于预留了空间，这时在父组件中使用子组件时，可以传递不同的内容。</p>
<p>下面看一下插槽的应用</p>
<p>基本使用方式</p>
<p>第一：确定插槽的位置</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;alert-box&quot;</span>, &#123;</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`</span></span><br><span class="line"><span class="string">   &lt;div class=&quot;demo-alert-box&quot;&gt;</span></span><br><span class="line"><span class="string">		&lt;strong&gt;子组件&lt;/strong&gt;</span></span><br><span class="line"><span class="string">	    &lt;slot&gt;&lt;/slot&gt;</span></span><br><span class="line"><span class="string">   &lt;/div&gt;</span></span><br><span class="line"><span class="string">`</span>,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在子组件中，通过<code>&lt;slot&gt;</code>确定出插槽的位置。</p>
<p>第二：插槽内容</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">alert-box</span>&gt;</span>Hello World<span class="tag">&lt;/<span class="name">alert-box</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>向插槽中传递内容。</p>
<p>下面看一下具体的代码：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;插槽基本使用&lt;/title&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;alert-box&gt;程序出现了bug&lt;/alert-box&gt;</span><br><span class="line">      &lt;alert-box&gt;程序出现了警告&lt;/alert-box&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script src=&quot;./vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      Vue.component(&quot;alert-box&quot;, &#123;</span><br><span class="line">        template: `</span><br><span class="line">                &lt;div&gt;</span><br><span class="line">                    &lt;strong&gt;ERROR:&lt;/strong&gt;</span><br><span class="line">                    &lt;slot&gt;&lt;/slot&gt;</span><br><span class="line">                &lt;/div&gt;    </span><br><span class="line">            `,</span><br><span class="line">      &#125;);</span><br><span class="line">      const vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;&#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>通过上面的代码我们可以看到，在<code>alert-box</code>这个组件中，定义了一个插槽，也就是预留了一个位置，下面使用该组件的时候，都可以向该插槽中传递数据。而<code>&lt;strong&gt;</code>标签中的内容就相当于是一个公共的内容了。</p>
<p>当然在插槽中也是可以添加默认的内容的。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&lt;div id=<span class="string">&quot;app&quot;</span>&gt;</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">alert-box</span>&gt;</span>程序出现了bug<span class="tag">&lt;/<span class="name">alert-box</span>&gt;</span></span></span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">alert-box</span>&gt;</span>程序出现了警告<span class="tag">&lt;/<span class="name">alert-box</span>&gt;</span></span></span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">alert-box</span>&gt;</span><span class="tag">&lt;/<span class="name">alert-box</span>&gt;</span></span></span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">    Vue.component(&quot;alert-box&quot;, &#123;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">      template: `</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">              <span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">                  <span class="tag">&lt;<span class="name">strong</span>&gt;</span>ERROR:<span class="tag">&lt;/<span class="name">strong</span>&gt;</span></span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">                  <span class="tag">&lt;<span class="name">slot</span>&gt;</span>默认内容<span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">              <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">          `,</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">    &#125;);</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">    const vm = new Vue(&#123;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">      el: &quot;#app&quot;,</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">      data: &#123;&#125;,</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">    &#125;);</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"><span class="language-xml">  </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们给插槽添加了默认的内容，如果在使用<code>alert-box</code>组件的时候，没有给插槽传递值，就会展示插槽中的默认内容。</p>
<h3 id="14-2-具名插槽"><a href="#14-2-具名插槽" class="headerlink" title="14.2 具名插槽"></a>14.2 具名插槽</h3><p>所谓的具名插槽就是有名字的插槽。</p>
<p>第一：插槽定义</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;container&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">header</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;header&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">header</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">main</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">slot</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">main</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">footer</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;footer&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">footer</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>第二：插槽内容</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">base-layout</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h1</span> <span class="attr">slot</span>=<span class="string">&quot;header&quot;</span>&gt;</span>标题内容<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>主要内容<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span>&gt;</span>主要内容<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">p</span> <span class="attr">slot</span>=<span class="string">&quot;footer&quot;</span>&gt;</span>底部内容<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">base-layout</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>下面我们来看一下具体的代码实现</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>具名插槽<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">base-layout</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">p</span> <span class="attr">slot</span>=<span class="string">&quot;header&quot;</span>&gt;</span>头部内容<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">p</span>&gt;</span>主要内容1<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">p</span>&gt;</span>主要内容2<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">p</span> <span class="attr">slot</span>=<span class="string">&quot;footer&quot;</span>&gt;</span>底部信息<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">base-layout</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      Vue.component(&quot;base-layout&quot;, &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;<span class="name">header</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;header&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     <span class="tag">&lt;/<span class="name">header</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     <span class="tag">&lt;<span class="name">main</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;<span class="name">slot</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     <span class="tag">&lt;/<span class="name">main</span>&gt;</span> </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     <span class="tag">&lt;<span class="name">footer</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;footer&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     <span class="tag">&lt;/<span class="name">footer</span>&gt;</span>   </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span>    </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            `,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data: &#123;&#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，<code> &lt;p slot=&quot;header&quot;&gt;头部内容&lt;/p&gt;</code>会插入到<code>base-layout</code> 组件的<code>header</code>这个插槽中。</p>
<p><code> &lt;p slot=&quot;footer&quot;&gt;底部信息&lt;/p&gt;</code>会插入到<code>footer</code>这个插槽中。</p>
<p>剩余的内容会插入到默认的（没有名称）的插槽内。</p>
<p>在上面的应用中，有一个问题就是，我们把插槽的名称给了某个<code>html</code>标签，例如<code>p</code>标签，这样就只能将该标签插入到插槽中。</p>
<p>但是，在实际的应用中，有可能需要向插槽中插入大量的内容，这时就需要用到<code>template</code>标签。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>具名插槽<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- &lt;base-layout&gt;</span></span><br><span class="line"><span class="comment">        &lt;p slot=&quot;header&quot;&gt;头部内容&lt;/p&gt;</span></span><br><span class="line"><span class="comment">        &lt;p&gt;主要内容1&lt;/p&gt;</span></span><br><span class="line"><span class="comment">        &lt;p&gt;主要内容2&lt;/p&gt;</span></span><br><span class="line"><span class="comment">        &lt;p slot=&quot;footer&quot;&gt;底部信息&lt;/p&gt;</span></span><br><span class="line"><span class="comment">      &lt;/base-layout&gt; --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">base-layout</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">slot</span>=<span class="string">&quot;header&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">div</span>&gt;</span>标题名称<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">div</span>&gt;</span>标题区域的布局<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span>&gt;</span>中间内容区域的布局实现<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">slot</span>=<span class="string">&quot;footer&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">div</span>&gt;</span>底部信息<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">div</span>&gt;</span>对底部内容区域进行布局<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">base-layout</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      Vue.component(&quot;base-layout&quot;, &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;<span class="name">header</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;header&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     <span class="tag">&lt;/<span class="name">header</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     <span class="tag">&lt;<span class="name">main</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;<span class="name">slot</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     <span class="tag">&lt;/<span class="name">main</span>&gt;</span> </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     <span class="tag">&lt;<span class="name">footer</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;footer&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     <span class="tag">&lt;/<span class="name">footer</span>&gt;</span>   </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                     </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span>    </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            `,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data: &#123;&#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们给<code>template</code>标签添加了插槽的名称，并且在<code>template</code>标签中嵌入了其它的多个标签，从而完成布局。</p>
<p>在这里，可以统一查看浏览器端所生成的代码结构。</p>
<h3 id="14-3-作用域插槽"><a href="#14-3-作用域插槽" class="headerlink" title="14.3 作用域插槽"></a>14.3 作用域插槽</h3><p>应用场景：父组件对子组件的内容进行加工处理。这也是作用域插槽的一个很重要特性，</p>
<p>下面我们通过一个例子来体会一下这句话的作用。</p>
<p>首先，我们先创建一个用户列表。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>作用域插槽<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-list</span> <span class="attr">:list</span>=<span class="string">&quot;userList&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-list</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      Vue.component(&quot;user-list&quot;, &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        props: [&quot;list&quot;],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;<span class="name">li</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span> <span class="attr">v-for</span>=<span class="string">&#x27;item in list&#x27;</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.userName</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                 <span class="tag">&lt;/<span class="name">ul</span>&gt;</span>   </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          userList: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 1,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;张三&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 2,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;李四&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 3,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;王五&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们首先创建了一个<code>user-list</code>组件，在这个组件中接收父组件传递过来的用户数据，通过循环的方式展示传递过来的用户数据。</p>
<p>现在，这里有一个新的需求，就是修改某个用户名的颜色，让其高亮显示。这个需求应该怎样来处理呢？</p>
<p>我们是否可以在子组件<code>user-list</code>中实现这个功能呢？</p>
<p>虽然可以，但是一般不建议你这么做，因为一个组件创建好以后，一般不建议修改。你可以想一下，如果这个组件是其它人创建的，而且很多人都在用，如果直接修改这个子组件，就会造成很多的问题。</p>
<p>所以这里，还是从父组件中进行修改。也是通过父组件来决定子组件中的哪个用户名进行高亮显示。</p>
<p>下面对代码进行修改：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>作用域插槽<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-list</span> <span class="attr">:list</span>=<span class="string">&quot;userList&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">slot-scope</span>=<span class="string">&quot;slotProps&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">strong</span> <span class="attr">v-if</span>=<span class="string">&quot;slotProps.info.id===2&quot;</span></span></span><br><span class="line"><span class="tag">            &gt;</span>&#123;&#123;slotProps.info.userName&#125;&#125;&lt;/strong</span><br><span class="line">          &gt;</span><br><span class="line">          <span class="tag">&lt;<span class="name">span</span> <span class="attr">v-else</span>&gt;</span>&#123;&#123;slotProps.info.userName&#125;&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">user-list</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      Vue.component(&quot;user-list&quot;, &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        props: [&quot;list&quot;],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;<span class="name">li</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span> <span class="attr">v-for</span>=<span class="string">&#x27;item in list&#x27;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;<span class="name">slot</span> <span class="attr">:info</span>=<span class="string">&quot;item&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                            </span><span class="template-variable">&#123;&#123;<span class="name">item.userName</span>&#125;&#125;</span><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                            <span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                 <span class="tag">&lt;/<span class="name">ul</span>&gt;</span>   </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          userList: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 1,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;张三&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 2,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;李四&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 3,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;王五&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>通过上面的代码可以看到，为了能够实现父组件决定子组件中哪个用户名能够高亮显示，需要在设计子组件的时候，为其添加对应的插槽。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line">template: `</span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span> <span class="attr">v-for</span>=<span class="string">&quot;item in list&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">slot</span> <span class="attr">:info</span>=<span class="string">&quot;item&quot;</span>&gt;</span> &#123;&#123;item.userName&#125;&#125; <span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">`,</span><br></pre></td></tr></table></figure>

<p>在子组件的<code>template</code>模板中，添加了插槽，同时为其动态绑定一个属性<code>info</code>(这个属性的名字是可以随意命名的)，该属性的值为用户的信息。</p>
<p>绑定该属性的目的就是为了能够在父组件中获取用户的信息。</p>
<p>下面看一下父组件中的修改</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;user-list :list=&quot;userList&quot;&gt;</span><br><span class="line">        &lt;template slot-scope=&quot;slotProps&quot;&gt;</span><br><span class="line">          &lt;strong v-if=&quot;slotProps.info.id===2&quot;</span><br><span class="line">            &gt;&#123;&#123;slotProps.info.userName&#125;&#125;&lt;/strong</span><br><span class="line">          &gt;</span><br><span class="line">          &lt;span v-else&gt;&#123;&#123;slotProps.info.userName&#125;&#125;&lt;/span&gt;</span><br><span class="line">        &lt;/template&gt;</span><br><span class="line">      &lt;/user-list&gt;</span><br><span class="line">    &lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>父组件在使用子组件<code>user-list</code>的时候，这里为其添加了<code>template</code>这个标签，而且这个标签的属性<code>slot-scope</code>是固定的，为其指定了一个值为<code>slotProps</code>,该值中，存储的就是从子组件中获取到的用户数据。</p>
<p>所以接下来通过<code>slotProps</code>获取<code>info</code>（注意这里要与子组件中的<code>slot</code>属性保持一致）中的用户数据。然后进行判断，如果用户编号为 2 的，为其加错，否者正常展示。</p>
<p>通过以上的案例，我们可以看到父组件通过作用域插槽实现了对子组件中数据的处理。其实这也就是为什么叫做作用域插槽的原因：</p>
<p>是因为模板虽然是在父级作用域（父组件）中渲染的，却能拿到子组件的数据。</p>
<h3 id="14-4-作用域插槽案例"><a href="#14-4-作用域插槽案例" class="headerlink" title="14.4. 作用域插槽案例"></a>14.4. 作用域插槽案例</h3><p>下面，我们通过一个列表的案例，来体会一下作用域插槽的应用。</p>
<p>首先我们先来做一个基本的列表组件</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/%E5%88%97%E8%A1%A8.png"></p>
<p>这里，我们首先使用的是具名插槽完成的，如下代码所示：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>作用域插槽案例<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">my-list</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">slot</span>=<span class="string">&quot;title&quot;</span>&gt;</span> 用户列表 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">slot</span>=<span class="string">&quot;content&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">&quot;item in listData&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span>&gt;</span>&#123;&#123;item.userName&#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">my-list</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      Vue.component(&quot;my-list&quot;, &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;list&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;list-title&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;title&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;list-content&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;content&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            `,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          listData: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123; id: 1, userName: &quot;张三&quot; &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 2,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;李四&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 3,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;王五&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们在子组件<code>my-list</code>中使用了<code>具名插槽</code>。然后父组件在使用子组件<code>my-list</code>的时候，可以通过<code>template</code>标签加上<code>slot</code>属性向具名插槽中传递数据。</p>
<p>虽然以上的写法满足了基本的需求，但是作为组件的使用者，这样的一个组件会让我们感觉非常的麻烦，也就是我们在使用<code>my-list</code>这个组件的时候，还需要自己去编写<code>content</code>区域的循环逻辑。这样就比较麻烦了，下面对上面的代码在做一些修改。</p>
<p>为了解决这个问题，我们可以把循环写到子组件中，这样我们在使用的时候，不需要写循环了，只是传递数据就可以了，这样就方便多了。其实这里我们就可以不用具名插槽了。</p>
<p>所以修改后的代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>作用域插槽案例<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">my-list</span> <span class="attr">title</span>=<span class="string">&quot;用户列表&quot;</span> <span class="attr">:content</span>=<span class="string">&quot;listData&quot;</span>&gt;</span> <span class="tag">&lt;/<span class="name">my-list</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      Vue.component(&quot;my-list&quot;, &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        props: [&quot;title&quot;, &quot;content&quot;],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;list&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;list-title&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        </span><span class="template-variable">&#123;&#123;<span class="name">title</span>&#125;&#125;</span><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;list-content&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;<span class="name">ul</span> <span class="attr">class</span>=<span class="string">&quot;list-content&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                            <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">&quot;item in content&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.userName</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;/<span class="name">ul</span>&gt;</span> </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            `,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          listData: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123; id: 1, userName: &quot;张三&quot; &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 2,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;李四&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 3,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;王五&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们没有使用插槽，直接将数据传递到子组件<code>my-list</code>中，然后在该子组件中接收到数据，并进行了循环遍历。</p>
<p>经过这一次的改造，满足了我们前面所提到的易用性问题，但是现在又有了新的问题，组件的拓展性不好。</p>
<p>每次只能生成相同结构的列表，一旦业务需要发生了变化，组件就不再使用了。比如，我现在有了新的需求，在一个列表的每个列表项前面加上一个小的<code>logo</code>,我总不能又写一个新的组件来适应需求的变化吧？</p>
<p>这里就可以使用作用域插槽来解决这个问题。</p>
<p>具体的实现代码如下所示：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>作用域插槽案例<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 如果没有传递模板，那么子组件的插槽中只会展示用户名 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">my-list</span> <span class="attr">title</span>=<span class="string">&quot;用户列表&quot;</span> <span class="attr">:content</span>=<span class="string">&quot;listData&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">my-list</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 传递模板 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">my-list</span> <span class="attr">title</span>=<span class="string">&quot;用户列表2&quot;</span> <span class="attr">:content</span>=<span class="string">&quot;listData&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">slot-scope</span>=<span class="string">&quot;scope&quot;</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;./one.png&quot;</span> <span class="attr">width</span>=<span class="string">&quot;20&quot;</span> /&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">span</span>&gt;</span>&#123;&#123;scope.item.userName&#125;&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">my-list</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;./vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-handlebars"><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      Vue.component(&quot;my-list&quot;, &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        props: [&quot;title&quot;, &quot;content&quot;],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        template: `</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;list&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;list-title&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        </span><span class="template-variable">&#123;&#123;<span class="name">title</span>&#125;&#125;</span><span class="language-xml"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;list-content&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars"></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                   <span class="tag">&lt;<span class="name">ul</span> <span class="attr">class</span>=<span class="string">&quot;list-content&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                            <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">&quot;item in content&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                           <span class="comment">&lt;!--这里将content中的每一项数据绑定到slot的itemb变量上，在父组件中就可以获取到item变量--&gt;</span>     </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;<span class="name">slot</span> <span class="attr">:item</span>=<span class="string">&quot;item&quot;</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item.userName</span>&#125;&#125;</span><span class="language-xml"><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                                </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                                <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                        <span class="tag">&lt;/<span class="name">ul</span>&gt;</span> </span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            `,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      const vm = new Vue(&#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        el: &quot;#app&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        data: &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          listData: [</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123; id: 1, userName: &quot;张三&quot; &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 2,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;李四&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#123;</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              id: 3,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">              userName: &quot;王五&quot;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">            &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">          ],</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">        &#125;,</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">      &#125;);</span></span></span><br><span class="line"><span class="language-xml"><span class="language-handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们首先在子组件<code>my-list</code>中，添加了作用域的插槽。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">ul</span> <span class="attr">class</span>=<span class="string">&quot;list-content&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">&quot;item in content&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--这里将content中的每一项数据绑定到slot的itemb变量上，在父组件中就可以获取到item变量--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">slot</span> <span class="attr">:item</span>=<span class="string">&quot;item&quot;</span>&gt;</span>&#123;&#123;item.userName&#125;&#125;<span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>同时在父组件中，使用对应的插槽</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- 如果没有传递模板，那么子组件的插槽中只会展示用户名 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">my-list</span> <span class="attr">title</span>=<span class="string">&quot;用户列表&quot;</span> <span class="attr">:content</span>=<span class="string">&quot;listData&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">my-list</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- 传递模板 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">my-list</span> <span class="attr">title</span>=<span class="string">&quot;用户列表2&quot;</span> <span class="attr">:content</span>=<span class="string">&quot;listData&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">template</span> <span class="attr">slot-scope</span>=<span class="string">&quot;scope&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;./one.png&quot;</span> <span class="attr">width</span>=<span class="string">&quot;20&quot;</span> /&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">span</span>&gt;</span>&#123;&#123;scope.item.userName&#125;&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">my-list</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>再回到开始的问题，作用域插槽到底是干嘛用的？很显然，它的作用就如官网所说的一样：将组件的数据暴露出去。而这么做，给了组件的使用者根据数据定制模板的机会，组件不再是写死成一种特定的结构。</p>
<p>以上就是作用域插槽的应用，需要你仔细体会。</p>
<p>那么，在这里再次问一个问题，就是在你所使用的<code>Vue</code>插件或者是第三方的库中，有没有遇到使用作用域插槽的情况呢？</p>
<p>其实，比较典型的就是<code>element-ui</code>的<code>table</code>组件，它就可以通过添加作用域插槽改变渲染的原始数据。</p>
<p>如下图所示：</p>
<p><img src= "" data-lazy-src="/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F%E6%8F%92%E6%A7%BD.png"></p>
<h3 id="14-5-插槽应用总结"><a href="#14-5-插槽应用总结" class="headerlink" title="14.5 插槽应用总结"></a>14.5 插槽应用总结</h3><p><strong>为什么要使用插槽</strong></p>
<p>组件的最大特性就是复用性，而用好插槽能大大提高组件的可复用能力。</p>
<p>组件的复用性常见情形如<em>在有相似功能的模块中，他们具有类似的 UI 界面，通过使用组件间的通信机制传递数据，从而达到一套代码渲染不同数据的效果</em>。</p>
<p>然而这种利用组件间通信的机制只能满足在结构上相同，渲染数据不同的情形；假设两个相似的页面，他们只在某一模块（区域）有不同的<code>UI</code>效果(例如，前面所做的列表，发现可以显示不同的<code>ui</code>效果)，以上办法就做不到了。可能你会想，使用 <code>v-if</code> 和 <code>v-else</code>来特殊处理这两个功能模块，不就解决了？很优秀，解决了，但不完美。极端一点，假设我们有一百个这种页面，就需要写一百个<code>v-if</code>、<code>v-else-if</code>、<code>v-else</code>来处理？那组件看起来将不再简小精致，维护起来也不容易。</p>
<p>而 插槽 “**<code>SLOT</code>**”就可以完美解决这个问题</p>
<p><strong>什么情况下使用插槽</strong></p>
<p>顾名思义，插槽即往卡槽中插入一段功能块。还是举刚才的例子。如果有一百个基本相似，只有一个模块功能不同的页面，而我们只想写一个组件。可以将不同的那个模块单独处理成一个卡片，在需要使用的时候将对应的卡片插入到组件中即可实现对应的完整的功能页。而不是在组件中把所有的情形用<code>if-else</code>罗列出来（这里还是体会用户列表的案例）</p>
<p>可能你会想，那我把一个组件分割成一片片的插槽，需要什么拼接什么，岂不是只要一个组件就能完成所有的功能？思路上没错，但是需要明白的是，卡片是在父组件上代替子组件实现的功能，使用插槽无疑是在给父组件页面增加规模，如果全都使用拼装的方式，和不用组件又有什么区别（例如，用户列表案例中需要其他的显示方式，需要在父组件中进行添加）。因此，<strong>插槽并不是用的越多越好</strong>。</p>
<p><strong>插槽是组件最大化利用的一种手段，而不是替代组件的策略，当然也不能替代组件</strong>。如果能在组件中实现的模块，或者只需要使用一次<code>v-else</code>， 或一次<code>v-else-if</code>，<code>v-else</code>就能解决的问题，都建议直接在组件中实现。</p>
<h2 id="15、Vue组件化的理解"><a href="#15、Vue组件化的理解" class="headerlink" title="15、Vue组件化的理解"></a>15、<code>Vue</code>组件化的理解</h2><p>关于<code>Vue</code>组件的内容，我们已经学习很多了，那么你能谈一下对<code>Vue</code>组件化的理解吗？</p>
<p>其实这也是一个比较常见的面试题。</p>
<p>当然，这个问题的面是非常广的。可以通过以下几点来描述：</p>
<p><strong>定义</strong>：组件是可复用的<code>Vue</code>实例，准确讲它是<code>VueComponent</code>的实例，继承自<code>Vue</code></p>
<p>优点：组件化可以增加代码的复用性，可维护性和可测试性。</p>
<p><strong>使用场景</strong>：什么时候使用组件？以下分类可以作为参数</p>
<p>第一：通用组件：实现最基本的功能，具有通用性，复用性。例如按钮组件，输入框组件，布局组件等。(<code>Element UI</code>组件库就是属于这种通用的组件)</p>
<p>第二：业务组件，用于完成具体的业务，具有一定的复用性。例如登录组件，轮播图组件。</p>
<p>第三：页面组件，组织应用各部分独立内容，需要时在不同页面组件间切换，例如：商品列表页，详情页组件。</p>
<p><strong>如何使用组件</strong></p>
<ul>
<li><p>定义：<code>Vue.component()</code>，<code>components</code>选项</p>
</li>
<li><p>分类：有状态组件(有 data 属性)，<code>functional</code></p>
</li>
<li><p>通信：<code>props</code>，<code>$emit()/$on()</code>，<code>provide/inject</code></p>
</li>
<li><p>内容分发：<code>&lt;slot&gt;</code>，<code>&lt;template&gt;</code>，<code>v-slot </code></p>
</li>
<li><p>使用及优化：<code>is</code>，<code>keep-alive</code>，<code>异步组件</code>(这些内容在后面的课程中会详细的讲解)</p>
</li>
</ul>
<p><strong>组件的本质吗</strong></p>
<p><code>vue</code>中的组件经历如下过程 组件配置 &#x3D;&gt;<code> VueComponent</code>实例 &#x3D;&gt; <code>render() </code>&#x3D;&gt; <code>Virtual DOM</code>&#x3D;&gt; <code>DOM</code><br>所以组件的本质是产生虚拟<code>DOM</code></p>
<p>关于这块内容，在后面的课程中还会深入的探讨，包虚拟<code>dom</code>,以及<code>vue</code>的源码。</p>
<h2 id="16、常用API说明"><a href="#16、常用API说明" class="headerlink" title="16、常用API说明"></a>16、常用<code>API</code>说明</h2><h3 id="16-1-Vue-set"><a href="#16-1-Vue-set" class="headerlink" title="16.1  Vue.set"></a>16.1 <code> Vue.set</code></h3><p>向响应式对象中添加一个属性，并确保这个新属性同样是响应式的，且会触发视图更新。</p>
<p>使用方法：<code>Vue.set(target,propertyName,value)</code></p>
<p>下面通过一个案例来演示一下,这个案例是在以前所做的用户列表的案例上进行修改的，</p>
<p>这里需求是给每个用户动态的添加身高。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>列表渲染<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.actived</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span> <span class="attr">v-if</span>=<span class="string">&quot;users.length===0&quot;</span>&gt;</span>没有任何用户数据<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">ul</span> <span class="attr">v-else</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span></span></span><br><span class="line"><span class="tag">          <span class="attr">v-for</span>=<span class="string">&quot;(item,index) in users&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">:style</span>=<span class="string">&quot;&#123;backgroundColor:selectItem===item?&#x27;#dddddd&#x27;:&#x27;transparent&#x27;&#125;&quot;</span></span></span><br><span class="line"><span class="tag">          @<span class="attr">mousemove</span>=<span class="string">&quot;selectItem=item&quot;</span></span></span><br><span class="line"><span class="tag">        &gt;</span></span><br><span class="line">          编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---身高:&#123;&#123;item.height&#125;&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>总人数：&#123;&#123;totalCount&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">num</span>: <span class="number">100</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: [],</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//组件实例已创建时</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">async</span> <span class="title function_">created</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">const</span> users = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">getUserList</span>();</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">users</span> = users;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新用户身高</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="title function_">batchUpdate</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新身高，动态的给users中添加身高属性</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              c.<span class="property">height</span> = <span class="number">0</span>;</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getTotal</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;methods&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> + <span class="string">&quot;个&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getUserList</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="title function_">resolve</span>([</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">3</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;老王&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                ]);</span></span><br><span class="line"><span class="language-javascript">              &#125;, <span class="number">2000</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">watch</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="comment">//立即执行</span></span></span><br><span class="line"><span class="language-javascript">            <span class="title function_">handler</span>(<span class="params">newValue, oldValue</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">totalCount</span> = newValue.<span class="property">length</span> + <span class="string">&quot;个人&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我首先把列表中，展示的内容做了一个修改，这里不在显示索引值，而是展示身高。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---身高:&#123;&#123;item.height&#125;&#125;</span><br></pre></td></tr></table></figure>

<p>但是我们知道在<code>users</code>中是没有<code>height</code>这个属性的，所以下面可以动态添加这个属性。</p>
<p>所以在<code>create</code>方法中，调用了<code>batchUpdate</code>方法，来动态更新。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//组件实例已创建时</span></span><br><span class="line">    <span class="keyword">async</span> <span class="title function_">created</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="keyword">const</span> users = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">getUserList</span>();</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">users</span> = users;</span><br><span class="line">      <span class="comment">//批量更新用户身高</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="title function_">batchUpdate</span>();</span><br><span class="line">    &#125;,</span><br></pre></td></tr></table></figure>

<p>在<code>methods</code>中，添加了<code>batchUpdate</code>方法。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//批量更新身高，动态的给users中添加身高属性</span></span><br><span class="line">        <span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span><br><span class="line">          <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span><br><span class="line">            c.<span class="property">height</span> = <span class="number">0</span>;</span><br><span class="line">          &#125;);</span><br><span class="line">        &#125;,</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，对<code>users</code>进行遍历，每遍历一次，取出一个对象后，动态添加一个属性<code>height</code>,并且初始值为 0.</p>
<p>这样刷新浏览器，可以看到对应的效果。</p>
<p>下面，我们在做一个功能，就是用户在一个文本框中，输入一个身高值，单击按钮，统一把所有用户的身高进行更新。</p>
<p>首先在<code>data</code>中添加一个属性<code>height</code>,该属性会与文本框进行绑定。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">data</span>: &#123;</span><br><span class="line">         <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">         <span class="attr">num</span>: <span class="number">100</span>,</span><br><span class="line">         <span class="attr">totalCount</span>: <span class="number">0</span>,</span><br><span class="line">         <span class="attr">users</span>: [],</span><br><span class="line">         <span class="attr">height</span>: <span class="number">0</span>,</span><br><span class="line">       &#125;,</span><br></pre></td></tr></table></figure>

<p>下面创建文本框，以及更新按钮</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model.number</span>=<span class="string">&quot;height&quot;</span> /&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;batchUpdate&quot;</span>&gt;</span>批量更新用户身高<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在这里我们需要在文本框中输入的值为数字类型，所以添加了一个<code>number</code>的后缀。现在，文本框与<code>height</code>属性绑定在一起了。下面单击按钮后，还是去执行<code>batchUpdate</code>方法。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//批量更新身高，动态的给users中添加身高属性</span></span><br><span class="line">         <span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span><br><span class="line">           <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span><br><span class="line">             c.<span class="property">height</span> = <span class="variable language_">this</span>.<span class="property">height</span>;</span><br><span class="line">           &#125;);</span><br><span class="line">         &#125;,</span><br></pre></td></tr></table></figure>

<p>这里我们可以看到，我们是用文本框中输入的值，更新了<code>users</code>数组中的<code>height</code>属性的值。</p>
<p>但是，当我们在浏览器中，单击按钮进行更新的时候，发现不起作用。</p>
<p>因为，现在动态所添加的<code>height</code>属性并不是响应式的。</p>
<p>但是，当把鼠标移动到列表项的时候，数据发生了变化，就是因为这时触发了我们给列表所添加的<code>mousemove</code></p>
<p>这个事件，导致页面重新刷新，这时发现数据发生变化了。</p>
<p>那么我们应该怎样解决这个问题呢？</p>
<p>这就需要，在<code>batchUpdate</code>方法中，使用<code>Vue.set()</code>方法</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span><br><span class="line">          <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">//   c.height = this.height;</span></span><br><span class="line">            <span class="title class_">Vue</span>.<span class="title function_">set</span>(c, <span class="string">&quot;height&quot;</span>, <span class="variable language_">this</span>.<span class="property">height</span>);</span><br><span class="line">          &#125;);</span><br><span class="line">        &#125;,</span><br></pre></td></tr></table></figure>

<p>修改的代码含义就是通过<code>Vue.set</code>方法，给<code>users</code>数组中每个对象，设置一个<code>height</code>属性，这时该属性就变成了响应式的，同时把 <code>data</code>中的<code>height</code>属性的值赋值给<code>height</code>.</p>
<p>完整代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>列表渲染<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.actived</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 批量更新身高 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model.number</span>=<span class="string">&quot;height&quot;</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;batchUpdate&quot;</span>&gt;</span>批量更新用户身高<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span> <span class="attr">v-if</span>=<span class="string">&quot;users.length===0&quot;</span>&gt;</span>没有任何用户数据<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">ul</span> <span class="attr">v-else</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">li</span></span></span><br><span class="line"><span class="tag">          <span class="attr">v-for</span>=<span class="string">&quot;(item,index) in users&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">:key</span>=<span class="string">&quot;item.id&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">:style</span>=<span class="string">&quot;&#123;backgroundColor:selectItem===item?&#x27;#dddddd&#x27;:&#x27;transparent&#x27;&#125;&quot;</span></span></span><br><span class="line"><span class="tag">          @<span class="attr">mousemove</span>=<span class="string">&quot;selectItem=item&quot;</span></span></span><br><span class="line"><span class="tag">        &gt;</span></span><br><span class="line">          编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---身高:&#123;&#123;item.height&#125;&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>总人数：&#123;&#123;totalCount&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">num</span>: <span class="number">100</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: [],</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">height</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//组件实例已创建时</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">async</span> <span class="title function_">created</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">const</span> users = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">getUserList</span>();</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">users</span> = users;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新用户身高</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="title function_">batchUpdate</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新身高，动态的给users中添加身高属性</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   c.height = this.height;</span></span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   Vue.set(c, &quot;height&quot;, this.height);</span></span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.$set(c, <span class="string">&quot;height&quot;</span>, <span class="variable language_">this</span>.<span class="property">height</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getTotal</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;methods&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> + <span class="string">&quot;个&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getUserList</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="title function_">resolve</span>([</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">3</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;老王&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                ]);</span></span><br><span class="line"><span class="language-javascript">              &#125;, <span class="number">2000</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">watch</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="comment">//立即执行</span></span></span><br><span class="line"><span class="language-javascript">            <span class="title function_">handler</span>(<span class="params">newValue, oldValue</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">totalCount</span> = newValue.<span class="property">length</span> + <span class="string">&quot;个人&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="16-2-Vue-delete"><a href="#16-2-Vue-delete" class="headerlink" title="16.2 Vue.delete"></a>16.2 <code>Vue.delete</code></h3><p>删除对象的属性，如果对象是响应式的，确保删除能触发更新视图。</p>
<p>使用方式：<code>Vue.delete(target,propertyName)</code></p>
<p>如果使用<code>delete obj[&#39;property&#39;]</code> 是不能更新页面的。</p>
<p>以上两个方法<code>Vue.set()</code>和<code>Vue.delete()</code>等同于以下两个实例方法。</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">vm.$set()</span><br><span class="line">vm.$delete()</span><br></pre></td></tr></table></figure>

<p><code>vm</code> 表示的是<code>Vue</code>的实例。</p>
<p>所以我们在<code>batchUpdate</code>中也可以采用如下的方式，来批量更新用户的身高数据。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span><br><span class="line">           <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span><br><span class="line">             <span class="comment">//   c.height = this.height;</span></span><br><span class="line">             <span class="comment">//   Vue.set(c, &quot;height&quot;, this.height);</span></span><br><span class="line">             <span class="variable language_">this</span>.$set(c, <span class="string">&quot;height&quot;</span>, <span class="variable language_">this</span>.<span class="property">height</span>);</span><br><span class="line">           &#125;);</span><br><span class="line">         &#125;,</span><br></pre></td></tr></table></figure>

<h3 id="16-3-vm-on与vm-emit"><a href="#16-3-vm-on与vm-emit" class="headerlink" title="16.3 vm.$on与vm.$emit"></a>16.3 <code>vm.$on</code>与<code>vm.$emit</code></h3><h4 id="16-3-1-列表组件设计"><a href="#16-3-1-列表组件设计" class="headerlink" title="16.3.1 列表组件设计"></a>16.3.1 列表组件设计</h4><p>这两个<code>api</code>在前面的课程中，我们也已经讲解过，主要用来实现:事件总线。</p>
<p>下面，我们将这两个<code>API</code>应用到用户列表这个案例中。主要是把<code>事件总线</code>这个应用再次复习一下。</p>
<p>当然，这里首先是把用户列表这个案例，按照我们前面所学习的组件的知识，进行拆分一下，实现组件化的应用。</p>
<p>初步改造后的代码，如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>列表渲染<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.actived</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 批量更新身高 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model.number</span>=<span class="string">&quot;height&quot;</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;batchUpdate&quot;</span>&gt;</span>批量更新用户身高<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 用户列表组件 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-list</span> <span class="attr">:users</span>=<span class="string">&quot;users&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-list</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>总人数：&#123;&#123;totalCount&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 用户列表组件创建</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-list&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">type</span>: <span class="title class_">Array</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">default</span>: [],</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">        &lt;div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;p v-if=&quot;users.length===0&quot;&gt;没有任何用户数据&lt;/p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;ul v-else&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;li</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                v-for=&quot;(item,index) in users&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                :key=&quot;item.id&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                :style=&quot;&#123;backgroundColor:selectItem===item?&#x27;#dddddd&#x27;:&#x27;transparent&#x27;&#125;&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                @mousemove=&quot;selectItem=item&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---身高:&#123;&#123;item.height&#125;&#125;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;/li&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;/ul&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">      &lt;/div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">        `</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">num</span>: <span class="number">100</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: [],</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">height</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//组件实例已创建时</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">async</span> <span class="title function_">created</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">const</span> users = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">getUserList</span>();</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">users</span> = users;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新用户身高</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="title function_">batchUpdate</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新身高，动态的给users中添加身高属性</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   c.height = this.height;</span></span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   Vue.set(c, &quot;height&quot;, this.height);</span></span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.$set(c, <span class="string">&quot;height&quot;</span>, <span class="variable language_">this</span>.<span class="property">height</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getTotal</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;methods&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> + <span class="string">&quot;个&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getUserList</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="title function_">resolve</span>([</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">3</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;老王&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                ]);</span></span><br><span class="line"><span class="language-javascript">              &#125;, <span class="number">2000</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">watch</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="comment">//立即执行</span></span></span><br><span class="line"><span class="language-javascript">            <span class="title function_">handler</span>(<span class="params">newValue, oldValue</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">totalCount</span> = newValue.<span class="property">length</span> + <span class="string">&quot;个人&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们首先创建了一个<code>user-list</code>组件，该组件首先会通过<code>props</code>接收传递过来的用户数据。</p>
<p>在这里我们将<code>props</code>定义成了对象的形式，这样更容易进行数据类型的校验，同时还可以设置默认值。</p>
<p>接下来将原来定义在<code>&lt;div id=&quot;app&quot;&gt;&lt;/div&gt;</code> 中的用户列表，要剪切到<code>user-list</code>组件的<code>template</code>属性中，同时，我们知道在列表中会用到<code>selectItem</code>属性，所以在<code>user-list</code>的<code>data</code>中定义该属性，父组件就不用在定义该属性了。</p>
<p>下面，我们在<code>&lt;div id=&quot;app&quot;&gt;&lt;/div&gt;</code>中使用该组件,并且传递了用户数据。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 用户列表组件 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">user-list</span> <span class="attr">:users</span>=<span class="string">&quot;users&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-list</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>现在用户列表的组件，在这里我们就创建好了。</p>
<h4 id="16-3-2-用户添加组件设计"><a href="#16-3-2-用户添加组件设计" class="headerlink" title="16.3.2 用户添加组件设计"></a>16.3.2 用户添加组件设计</h4><p>下面我们在创建一个组件，该组件封装了一个文本框和添加用户信息的按钮。</p>
<p>代码如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//新增用户组件</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-add&quot;</span>, &#123;</span><br><span class="line">  <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      <span class="attr">userInfo</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`</span></span><br><span class="line"><span class="string">            &lt;div&gt;</span></span><br><span class="line"><span class="string">             &lt;p&gt;</span></span><br><span class="line"><span class="string">                &lt;input type=&quot;text&quot; v-model=&quot;userInfo&quot; v-on:keydown.enter=&quot;addUser&quot; /&gt;</span></span><br><span class="line"><span class="string">             &lt;/p&gt;</span></span><br><span class="line"><span class="string">             &lt;button @click=&quot;addUser&quot;&gt;新增用户&lt;/button&gt;</span></span><br><span class="line"><span class="string">              &lt;/div&gt;</span></span><br><span class="line"><span class="string">            `</span>,</span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="comment">//将输入的用户数据通知给父组件，来完成新增用户操作.</span></span><br><span class="line">      <span class="variable language_">this</span>.$emit(<span class="string">&quot;add-user&quot;</span>, <span class="variable language_">this</span>.<span class="property">userInfo</span>);</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">userInfo</span> = <span class="string">&quot;&quot;</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们创建了<code>user-add</code> 这个组件，该组件最终呈现的就是就是一个文本框与一个添加按钮。并且通过<code>v-model</code>将<code>userInfo</code>属性与文本框进行了绑定。同时，单击按钮的时候，执行<code>addUser</code>方法，在该方法中，通过<code>$emit</code>想父组件发送了一个事件，同时将用户在文本框中输入的数据也传递过去。</p>
<p>然后清空文本框，</p>
<p>下面看一下父组件的处理。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 新增用户 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">user-add</span> @<span class="attr">add-user</span>=<span class="string">&quot;addUser&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-add</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在<code>&lt;div id=&quot;app&quot;&gt;&lt;/div&gt;</code> 中使用<code>user-add</code>这个组件，同时接受传递过来的事件<code>add-user</code>,然后执行<code>addUser</code>方法。</p>
<p>下面看一下<code>addUser</code>这个方法的具体实现。</p>
<p>在<code>vue</code> 实例的<code>methods</code>属性中，添加<code>addUser</code>这个方法。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//添加用户的信息</span></span><br><span class="line">          <span class="title function_">addUser</span>(<span class="params">userInfo</span>) &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">push</span>(&#123;</span><br><span class="line">              <span class="attr">id</span>: <span class="variable language_">this</span>.<span class="property">users</span>[<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> - <span class="number">1</span>].<span class="property">id</span> + <span class="number">1</span>,</span><br><span class="line">              <span class="attr">name</span>: userInfo,</span><br><span class="line">            &#125;);</span><br><span class="line">          &#125;,</span><br></pre></td></tr></table></figure>

<p>接受用户在文本框中输入的数据，然后添加到<code>users</code>数组中。</p>
<p>完整代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>列表渲染<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.actived</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 批量更新身高 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model.number</span>=<span class="string">&quot;height&quot;</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;batchUpdate&quot;</span>&gt;</span>批量更新用户身高<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 新增用户 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-add</span> @<span class="attr">add-user</span>=<span class="string">&quot;addUser&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-add</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 用户列表组件 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-list</span> <span class="attr">:users</span>=<span class="string">&quot;users&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-list</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>总人数：&#123;&#123;totalCount&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//新增用户组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-add&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">userInfo</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;input type=&quot;text&quot; v-model=&quot;userInfo&quot; v-on:keydown.enter=&quot;addUser&quot; /&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;/p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;button @click=&quot;addUser&quot;&gt;新增用户&lt;/button&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;/div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            `</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//将输入的用户数据通知给父组件，来完成新增用户操作.</span></span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.$emit(<span class="string">&quot;add-user&quot;</span>, <span class="variable language_">this</span>.<span class="property">userInfo</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">userInfo</span> = <span class="string">&quot;&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 用户列表</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-list&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">type</span>: <span class="title class_">Array</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">default</span>: [],</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">        &lt;div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;p v-if=&quot;users.length===0&quot;&gt;没有任何用户数据&lt;/p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;ul v-else&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;li</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                v-for=&quot;(item,index) in users&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                :key=&quot;item.id&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                :style=&quot;&#123;backgroundColor:selectItem===item?&#x27;#dddddd&#x27;:&#x27;transparent&#x27;&#125;&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                @mousemove=&quot;selectItem=item&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---身高:&#123;&#123;item.height&#125;&#125;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;/li&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;/ul&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">      &lt;/div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">        `</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">num</span>: <span class="number">100</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: [],</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">height</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//组件实例已创建时</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">async</span> <span class="title function_">created</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">const</span> users = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">getUserList</span>();</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">users</span> = users;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新用户身高</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="title function_">batchUpdate</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//添加用户的信息</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">addUser</span>(<span class="params">userInfo</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">push</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">id</span>: <span class="variable language_">this</span>.<span class="property">users</span>[<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> - <span class="number">1</span>].<span class="property">id</span> + <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">name</span>: userInfo,</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新身高，动态的给users中添加身高属性</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   c.height = this.height;</span></span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   Vue.set(c, &quot;height&quot;, this.height);</span></span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.$set(c, <span class="string">&quot;height&quot;</span>, <span class="variable language_">this</span>.<span class="property">height</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getTotal</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;methods&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> + <span class="string">&quot;个&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getUserList</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="title function_">resolve</span>([</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">3</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;老王&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                ]);</span></span><br><span class="line"><span class="language-javascript">              &#125;, <span class="number">2000</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">watch</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="comment">//立即执行</span></span></span><br><span class="line"><span class="language-javascript">            <span class="title function_">handler</span>(<span class="params">newValue, oldValue</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">totalCount</span> = newValue.<span class="property">length</span> + <span class="string">&quot;个人&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="16-3-3-自定义组件实现双向绑定"><a href="#16-3-3-自定义组件实现双向绑定" class="headerlink" title="16.3.3 自定义组件实现双向绑定"></a>16.3.3 自定义组件实现双向绑定</h4><p>在上一个案例中，我们创建了一个<code>user-add</code>这个组件，完成用户信息的添加。</p>
<p>并且在该组件的内部，维护了所添加的用户信息。</p>
<p>假如，我不想让<code>user-add</code>这个组件来维护这个用户信息，而是让父组件来维护，应该怎样处理呢？</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 新增用户 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">user-add</span> @<span class="attr">add-user</span>=<span class="string">&quot;addUser&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;userInfo&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-add</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>将<code>userInfo</code>的值给<code>v-model</code>.</p>
<p>所以在父组件中要定义<code>userInfo</code></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">      <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span><br><span class="line">      <span class="attr">data</span>: &#123;</span><br><span class="line">        <span class="attr">num</span>: <span class="number">100</span>,</span><br><span class="line">        <span class="attr">totalCount</span>: <span class="number">0</span>,</span><br><span class="line">        <span class="attr">users</span>: [],</span><br><span class="line">        <span class="attr">height</span>: <span class="number">0</span>,</span><br><span class="line">        <span class="attr">userInfo</span>: <span class="string">&quot;abc&quot;</span>,</span><br><span class="line">      &#125;,</span><br></pre></td></tr></table></figure>

<p>下面看一下<code>user-add</code>组件的修改</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-add&quot;</span>, &#123;</span><br><span class="line">  <span class="comment">// data() &#123;</span></span><br><span class="line">  <span class="comment">//   return &#123;</span></span><br><span class="line">  <span class="comment">//     userInfo: &quot;&quot;,</span></span><br><span class="line">  <span class="comment">//   &#125;;</span></span><br><span class="line">  <span class="comment">// &#125;,</span></span><br><span class="line">  <span class="attr">props</span>: [<span class="string">&quot;value&quot;</span>],</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`</span></span><br><span class="line"><span class="string">            &lt;div&gt;</span></span><br><span class="line"><span class="string">             &lt;p&gt;</span></span><br><span class="line"><span class="string">                &lt;input type=&quot;text&quot; :value=&quot;value&quot; @input=&quot;onInput&quot; v-on:keydown.enter=&quot;addUser&quot; /&gt;</span></span><br><span class="line"><span class="string">             &lt;/p&gt;</span></span><br><span class="line"><span class="string">             &lt;button @click=&quot;addUser&quot;&gt;新增用户&lt;/button&gt;</span></span><br><span class="line"><span class="string">              &lt;/div&gt;</span></span><br><span class="line"><span class="string">            `</span>,</span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="comment">//将输入的用户数据通知给父组件，来完成新增用户操作.</span></span><br><span class="line">      <span class="comment">// this.$emit(&quot;add-user&quot;, this.userInfo);</span></span><br><span class="line">      <span class="variable language_">this</span>.$emit(<span class="string">&quot;add-user&quot;</span>);</span><br><span class="line">      <span class="comment">// this.userInfo = &quot;&quot;;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">onInput</span>(<span class="params">e</span>) &#123;</span><br><span class="line">      <span class="variable language_">this</span>.$emit(<span class="string">&quot;input&quot;</span>, e.<span class="property">target</span>.<span class="property">value</span>);</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在<code>user-add</code>组件中，定义<code>props</code>接收传递过来的值，也就是<code>userInfo</code>的值会传递给<code>value</code></p>
<p>下面修改<code>user-add</code>组件中的模板，文本框绑定<code>value</code>值。通过给其添加<code>input</code>事件，在文本框中输入值后，调用<code>onInput</code>方法，在该方法中获取用户在文本框中输入的值，然后发送<code>input</code>事件。对应的值传递给父组件中的<code>userInfo</code></p>
<p>同时单击“新增用户”按钮的时候，执行<code>addUser</code>方法，在该方法中发送事件<code>add-user</code>,也不需要传递数据了。</p>
<p>同时，父组件中的<code>addUser</code>方法实现如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span><br><span class="line">          <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">push</span>(&#123;</span><br><span class="line">            <span class="attr">id</span>: <span class="variable language_">this</span>.<span class="property">users</span>[<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> - <span class="number">1</span>].<span class="property">id</span> + <span class="number">1</span>,</span><br><span class="line">            <span class="attr">name</span>: <span class="variable language_">this</span>.<span class="property">userInfo</span>,</span><br><span class="line">          &#125;);</span><br><span class="line">          <span class="variable language_">this</span>.<span class="property">userInfo</span> = <span class="string">&quot;&quot;</span>;</span><br><span class="line">        &#125;,</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>直接从<code>data</code>中获取<code>userInfo</code>的数据。</p>
<p>总结：</p>
<p>以下的写法</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">user-add</span> @<span class="attr">add-user</span>=<span class="string">&quot;addUser&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;userInfo&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-add</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>等价以下的写法</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">user-add</span> <span class="attr">v-bind:value</span>=<span class="string">&quot;userInfo&quot;</span> <span class="attr">v-on:input</span>=<span class="string">&quot;userInfo = $event&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-add</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>也就是说<code>v-model</code>就是<code>v-bind</code>与<code>v-on</code>的语法糖。</p>
<p>在这里我们将<code>userInfo</code>的值给了<code>value</code>属性，而<code>value</code>属性传递到了<code>user-add</code>组件中，所以在<code>user-add</code>组件中要通过<code>props</code>来接收<code>value</code>属性的值。</p>
<p>在<code>user-add</code>组件的文本中，输入内容后触发<code>@input</code> 事件，对应的会调用<code>onInput</code>方法，在该方法中，执行了</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="variable language_">this</span>.$emit(<span class="string">&quot;input&quot;</span>, e.<span class="property">target</span>.<span class="property">value</span>);</span><br></pre></td></tr></table></figure>

<p>发送了<code>input</code>事件，并且传递了用户在文本框中输入的值。</p>
<p>那很明显，这时会触发下面代码中的<code>input</code>事件，将传递过来的值给<code>userInfo</code>属性。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">user-add</span> <span class="attr">v-bind:value</span>=<span class="string">&quot;userInfo&quot;</span> <span class="attr">v-on:input</span>=<span class="string">&quot;userInfo = $event&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-add</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>以上就是<code>v-model</code>的原理，希望仔细体会，这也是面试经常会被问到的问题。</p>
<h4 id="16-3-4-使用插槽完成内容分发"><a href="#16-3-4-使用插槽完成内容分发" class="headerlink" title="16.3.4. 使用插槽完成内容分发"></a>16.3.4. 使用插槽完成内容分发</h4><p>关于插槽的内容，在前面的的课程中我们已经学习过了，那么什么是内容分发呢？</p>
<p>其实就是在使用组件的时候，我们提供具体的数据内容，然后这些内容会插入到组件内部插槽的位置，这就是所谓的内容分发。</p>
<p>下面，要做的事情就是创建一个信息的提示窗口。例如：当添加用户成功后，给出相应的提示。</p>
<p>首先先创建样式：</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line">&lt;style&gt;</span><br><span class="line">     <span class="selector-class">.actived</span> &#123;</span><br><span class="line">       <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="selector-class">.message-box</span> &#123;</span><br><span class="line">       <span class="attribute">padding</span>: <span class="number">10px</span> <span class="number">20px</span>;</span><br><span class="line">       <span class="attribute">background-color</span>: <span class="number">#4fc</span>;</span><br><span class="line">       <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#42b</span>;</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="selector-class">.message-box-close</span> &#123;</span><br><span class="line">       <span class="attribute">float</span>: right;</span><br><span class="line">     &#125;</span><br><span class="line">   &lt;/style&gt;</span><br></pre></td></tr></table></figure>

<p>下面创建对应的组件。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//创建弹出的组件</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;message&quot;</span>, &#123;</span><br><span class="line">  <span class="comment">//show表示的含义，控制弹出窗口的显示与隐藏。</span></span><br><span class="line">  <span class="comment">//slot:表示占坑。也就是窗口中的内容，是通过外部组件传递过来的。</span></span><br><span class="line">  <span class="attr">props</span>: [<span class="string">&quot;show&quot;</span>],</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`&lt;div class=&#x27;message-box&#x27; v-if=&quot;show&quot;&gt;</span></span><br><span class="line"><span class="string">            &lt;slot&gt;&lt;/slot&gt;</span></span><br><span class="line"><span class="string">            &lt;span class=&quot;message-box-close&quot;&gt;关闭&lt;/span&gt;</span></span><br><span class="line"><span class="string">          &lt;/div&gt;`</span>,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>使用上面的组件</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- 弹窗组件 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">message</span> <span class="attr">:show</span>=<span class="string">&quot;isShow&quot;</span>&gt;</span> 添加用户成功 <span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- 批量更新身高 --&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在<code>data</code> 中定义<code>isShow</code>属性，初始值为<code>false</code>.</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">       <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span><br><span class="line">       <span class="attr">data</span>: &#123;</span><br><span class="line">         <span class="attr">num</span>: <span class="number">100</span>,</span><br><span class="line">         <span class="attr">totalCount</span>: <span class="number">0</span>,</span><br><span class="line">         <span class="attr">users</span>: [],</span><br><span class="line">         <span class="attr">height</span>: <span class="number">0</span>,</span><br><span class="line">         <span class="attr">userInfo</span>: <span class="string">&quot;abc&quot;</span>,</span><br><span class="line">         <span class="attr">isShow</span>: <span class="literal">false</span>,</span><br><span class="line">       &#125;,</span><br></pre></td></tr></table></figure>

<p>下面就是当用户完成添加的时候，弹出该窗口。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//添加用户的信息</span></span><br><span class="line">         <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span><br><span class="line">           <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">push</span>(&#123;</span><br><span class="line">             <span class="attr">id</span>: <span class="variable language_">this</span>.<span class="property">users</span>[<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> - <span class="number">1</span>].<span class="property">id</span> + <span class="number">1</span>,</span><br><span class="line">             <span class="attr">name</span>: <span class="variable language_">this</span>.<span class="property">userInfo</span>,</span><br><span class="line">           &#125;);</span><br><span class="line">           <span class="variable language_">this</span>.<span class="property">userInfo</span> = <span class="string">&quot;&quot;</span>;</span><br><span class="line">           <span class="comment">//完成用户添加后，给出相应的提示信息</span></span><br><span class="line">           <span class="variable language_">this</span>.<span class="property">isShow</span> = <span class="literal">true</span>;</span><br><span class="line">         &#125;,</span><br></pre></td></tr></table></figure>

<p>在<code>addUser</code>方法中完成了用户信息的添加后，将<code>isShow</code>的属性值设置为<code>true</code>.</p>
<p>这时弹出了对应的窗口。</p>
<p>下面要考虑的就是，单击窗口右侧的“关闭”按钮，将窗口关闭这个效果应该怎样实现。</p>
<p>首先给<code>关闭</code>按钮添加单击事件。</p>
<p>如下所示：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//创建弹出的组件</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;message&quot;</span>, &#123;</span><br><span class="line">  <span class="comment">//show表示的含义，控制弹出窗口的显示与隐藏。</span></span><br><span class="line">  <span class="comment">//slot:表示占坑。也就是窗口中的内容，是通过外部组件传递过来的。</span></span><br><span class="line">  <span class="attr">props</span>: [<span class="string">&quot;show&quot;</span>],</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`&lt;div class=&#x27;message-box&#x27; v-if=&quot;show&quot;&gt;</span></span><br><span class="line"><span class="string">            &lt;slot&gt;&lt;/slot&gt;</span></span><br><span class="line"><span class="string">            &lt;span class=&quot;message-box-close&quot; @click=&#x27;$emit(&quot;close&quot;,false)&#x27;&gt;关闭&lt;/span&gt;</span></span><br><span class="line"><span class="string">          &lt;/div&gt;`</span>,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>当单击关闭按钮后，会发送一个<code>close</code>事件，同时传递的值为<code>false</code>.</p>
<p>下面回到父组件中，对<code>close</code>事件进行处理。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 弹窗组件 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">message</span> <span class="attr">:show</span>=<span class="string">&quot;isShow&quot;</span> @<span class="attr">close</span>=<span class="string">&quot;closeWindow&quot;</span>&gt;</span> 添加用户成功 <span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>当<code>close</code>事件触发后，执行<code>closeWindow</code>方法。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//关闭窗口</span></span><br><span class="line">        <span class="title function_">closeWindow</span>(<span class="params">data</span>) &#123;</span><br><span class="line">          <span class="variable language_">this</span>.<span class="property">isShow</span> = data;</span><br><span class="line">        &#125;,</span><br></pre></td></tr></table></figure>

<p>在<code>closeWindow</code>方法中，根据子组件传递过来的值<code>false</code>,修改<code>isShow</code>属性的值，这时<code>isShow</code>的值为<code>false</code>.这时窗口关闭。</p>
<p>下面要解决的问题就是，在使用弹窗组件的时候，不仅能传递窗口的内容，还能传递其它的内容，例如标题等。</p>
<p>那应该怎样处理呢?</p>
<p>这里，可以使用<code>具名插槽</code></p>
<p>代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 弹窗组件 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">message</span> <span class="attr">:show</span>=<span class="string">&quot;isShow&quot;</span> @<span class="attr">close</span>=<span class="string">&quot;closeWindow&quot;</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- titile的插槽 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h2</span>&gt;</span>恭喜<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- 默认插槽 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">template</span>&gt;</span> 添加用户成功 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>下面修改一下<code>message</code>组件中的内容。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//创建弹出的组件</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;message&quot;</span>, &#123;</span><br><span class="line">  <span class="comment">//show表示的含义，控制弹出窗口的显示与隐藏。</span></span><br><span class="line">  <span class="comment">//slot:表示占坑。也就是窗口中的内容，是通过外部组件传递过来的。</span></span><br><span class="line">  <span class="attr">props</span>: [<span class="string">&quot;show&quot;</span>],</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`&lt;div class=&#x27;message-box&#x27; v-if=&quot;show&quot;&gt;</span></span><br><span class="line"><span class="string">             &lt;!--具名插槽--&gt;</span></span><br><span class="line"><span class="string">             &lt;slot name=&quot;title&quot;&gt;默认标题&lt;/slot&gt;</span></span><br><span class="line"><span class="string">            &lt;slot&gt;&lt;/slot&gt;</span></span><br><span class="line"><span class="string">            &lt;span class=&quot;message-box-close&quot; @click=&#x27;$emit(&quot;close&quot;,false)&#x27;&gt;关闭&lt;/span&gt;</span></span><br><span class="line"><span class="string">          &lt;/div&gt;`</span>,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在上面定义<code>message</code>组件的时候，指定了<code>具名插槽</code>，名称为<code>title</code>.要与在父组件中使用<code>message</code>组件的时候指定的名称保持一致，同时这里如果没有传递任何内容，将会显示”默认标题”。</p>
<p>完整代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>列表渲染<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.actived</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.message-box</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">10px</span> <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#4fc</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#42b</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.message-box-close</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">float</span>: right;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 弹窗组件 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">message</span> <span class="attr">:show</span>=<span class="string">&quot;isShow&quot;</span> @<span class="attr">close</span>=<span class="string">&quot;closeWindow&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- titile的插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:title</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">h2</span>&gt;</span>恭喜<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 默认插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span>&gt;</span> 添加用户成功 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 批量更新身高 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model.number</span>=<span class="string">&quot;height&quot;</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;batchUpdate&quot;</span>&gt;</span>批量更新用户身高<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 新增用户 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-add</span> @<span class="attr">add-user</span>=<span class="string">&quot;addUser&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;userInfo&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-add</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 用户列表组件 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-list</span> <span class="attr">:users</span>=<span class="string">&quot;users&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-list</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>总人数：&#123;&#123;totalCount&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//创建弹出的组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;message&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//show表示的含义，控制弹出窗口的显示与隐藏。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//slot:表示占坑。也就是窗口中的内容，是通过外部组件传递过来的。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;show&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`&lt;div class=&#x27;message-box&#x27; v-if=&quot;show&quot;&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;!--具名插槽--&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;slot name=&quot;title&quot;&gt;默认标题&lt;/slot&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;slot&gt;&lt;/slot&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;span class=&quot;message-box-close&quot; @click=&#x27;$emit(&quot;close&quot;,false)&#x27;&gt;关闭&lt;/span&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">          &lt;/div&gt;`</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//新增用户组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-add&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// data() &#123;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//   return &#123;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//     userInfo: &quot;&quot;,</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//   &#125;;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// &#125;,</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;value&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;input type=&quot;text&quot; :value=&quot;value&quot; @input=&quot;onInput&quot; v-on:keydown.enter=&quot;addUser&quot; /&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;/p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;button @click=&quot;addUser&quot;&gt;新增用户&lt;/button&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;/div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            `</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//将输入的用户数据通知给父组件，来完成新增用户操作.</span></span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// this.$emit(&quot;add-user&quot;, this.userInfo);</span></span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.$emit(<span class="string">&quot;add-user&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// this.userInfo = &quot;&quot;;</span></span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">onInput</span>(<span class="params">e</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.$emit(<span class="string">&quot;input&quot;</span>, e.<span class="property">target</span>.<span class="property">value</span>);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 用户列表</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-list&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">type</span>: <span class="title class_">Array</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">default</span>: [],</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">        &lt;div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;p v-if=&quot;users.length===0&quot;&gt;没有任何用户数据&lt;/p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;ul v-else&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;li</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                v-for=&quot;(item,index) in users&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                :key=&quot;item.id&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                :style=&quot;&#123;backgroundColor:selectItem===item?&#x27;#dddddd&#x27;:&#x27;transparent&#x27;&#125;&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                @mousemove=&quot;selectItem=item&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---身高:&#123;&#123;item.height&#125;&#125;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;/li&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;/ul&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">      &lt;/div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">        `</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">num</span>: <span class="number">100</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: [],</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">height</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">userInfo</span>: <span class="string">&quot;abc&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">isShow</span>: <span class="literal">false</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//组件实例已创建时</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">async</span> <span class="title function_">created</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">const</span> users = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">getUserList</span>();</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">users</span> = users;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新用户身高</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="title function_">batchUpdate</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//关闭窗口</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">closeWindow</span>(<span class="params">data</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">isShow</span> = data;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//添加用户的信息</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">push</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">id</span>: <span class="variable language_">this</span>.<span class="property">users</span>[<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> - <span class="number">1</span>].<span class="property">id</span> + <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">              <span class="attr">name</span>: <span class="variable language_">this</span>.<span class="property">userInfo</span>,</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">userInfo</span> = <span class="string">&quot;&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//完成用户添加后，给出相应的提示信息</span></span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">isShow</span> = <span class="literal">true</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新身高，动态的给users中添加身高属性</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   c.height = this.height;</span></span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   Vue.set(c, &quot;height&quot;, this.height);</span></span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.$set(c, <span class="string">&quot;height&quot;</span>, <span class="variable language_">this</span>.<span class="property">height</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getTotal</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;methods&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> + <span class="string">&quot;个&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getUserList</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="title function_">resolve</span>([</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">3</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;老王&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                ]);</span></span><br><span class="line"><span class="language-javascript">              &#125;, <span class="number">2000</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">watch</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="comment">//立即执行</span></span></span><br><span class="line"><span class="language-javascript">            <span class="title function_">handler</span>(<span class="params">newValue, oldValue</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">totalCount</span> = newValue.<span class="property">length</span> + <span class="string">&quot;个人&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="16-3-5-vm-on与vm-emit应用"><a href="#16-3-5-vm-on与vm-emit应用" class="headerlink" title="16.3.5 vm.$on与vm.$emit应用"></a>16.3.5 <code>vm.$on</code>与<code>vm.$emit</code>应用</h4><p>现在，关于用户管理这个案例的一些组件拆分，以及插槽的应用在这我们已经构建好了。</p>
<p>下面就看一下<code>vm.$on</code>与<code>vm.$emit</code>的应用。</p>
<p>根据前面的学习，我们知道<code>vm.$on</code>与<code>vm.$emit</code>的典型应用就是事件总线。</p>
<p>也就是通过在<code>Vue</code> 原型上添加一个<code>Vue</code>实例作为事件总线，实现组件间相互通信，而且不受组件间关系的影响</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Vue.prototype.$bus=new Vue()</span><br></pre></td></tr></table></figure>

<p>在所有组件最上面创建事件总线，</p>
<p>这样做的好处就是在任意组件中使用<code>this.$bus</code>访问到该<code>Vue</code>实例。</p>
<p>下面，我们来看一下事件总线的用法。</p>
<p>首先，我们这里先把事件总线创建出来。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//创建事件总线</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$bus</span> = <span class="keyword">new</span> <span class="title class_">Vue</span>();</span><br></pre></td></tr></table></figure>

<p>下面，在创建一个警告的窗口，也就是当单击“新增用户”按钮的时候，如果用户没有填写用户名给出相应册错误提示。</p>
<p>在这里先把样式修改一下：</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line">&lt;style&gt;</span><br><span class="line">     <span class="selector-class">.actived</span> &#123;</span><br><span class="line">       <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="selector-class">.message-box</span> &#123;</span><br><span class="line">       <span class="attribute">padding</span>: <span class="number">10px</span> <span class="number">20px</span>;</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="selector-class">.success</span> &#123;</span><br><span class="line">       <span class="attribute">background-color</span>: <span class="number">#4fc</span>;</span><br><span class="line">       <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#42b</span>;</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="selector-class">.warning</span> &#123;</span><br><span class="line">       <span class="attribute">background-color</span>: red;</span><br><span class="line">       <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#42b</span>;</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="selector-class">.message-box-close</span> &#123;</span><br><span class="line">       <span class="attribute">float</span>: right;</span><br><span class="line">     &#125;</span><br><span class="line">   &lt;/style&gt;</span><br></pre></td></tr></table></figure>

<p>然后创建出对应的窗口。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 警告 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">message</span> <span class="attr">:show</span>=<span class="string">&quot;showWarn&quot;</span> @<span class="attr">close</span>=<span class="string">&quot;closeWindow&quot;</span> <span class="attr">class</span>=<span class="string">&quot;warning&quot;</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- titile的插槽 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h2</span>&gt;</span>警告<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- 默认插槽 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">template</span>&gt;</span> 请输入用户名 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>注意：在上面的代码中，我们使用<code>showWarn</code>这个属性控制警告窗口的显示与隐藏。</p>
<p>同时，为其添加了<code>warning</code>样式，对应的成功的窗口需要添加<code>success</code> 样式。</p>
<p>同时在<code>data</code>中定义<code>showWarn</code>属性。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span><br><span class="line">        <span class="attr">data</span>: &#123;</span><br><span class="line">          <span class="attr">num</span>: <span class="number">100</span>,</span><br><span class="line">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span><br><span class="line">          <span class="attr">users</span>: [],</span><br><span class="line">          <span class="attr">height</span>: <span class="number">0</span>,</span><br><span class="line">          <span class="attr">userInfo</span>: <span class="string">&quot;abc&quot;</span>,</span><br><span class="line">          <span class="attr">isShow</span>: <span class="literal">false</span>,</span><br><span class="line">          <span class="attr">showWarn</span>: <span class="literal">false</span>, <span class="comment">// 控制警告窗口的显示与隐藏</span></span><br><span class="line">        &#125;,</span><br></pre></td></tr></table></figure>

<p>下面要修改的就是当单击”新增用户”按钮的时候，对<code>addUser</code>方法的修改。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//添加用户的信息</span></span><br><span class="line">         <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span><br><span class="line">           <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">userInfo</span>) &#123;</span><br><span class="line">             <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">push</span>(&#123;</span><br><span class="line">               <span class="attr">id</span>: <span class="variable language_">this</span>.<span class="property">users</span>[<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> - <span class="number">1</span>].<span class="property">id</span> + <span class="number">1</span>,</span><br><span class="line">               <span class="attr">name</span>: <span class="variable language_">this</span>.<span class="property">userInfo</span>,</span><br><span class="line">             &#125;);</span><br><span class="line">             <span class="variable language_">this</span>.<span class="property">userInfo</span> = <span class="string">&quot;&quot;</span>;</span><br><span class="line">             <span class="comment">//完成用户添加后，给出相应的提示信息</span></span><br><span class="line">             <span class="variable language_">this</span>.<span class="property">isShow</span> = <span class="literal">true</span>;</span><br><span class="line">           &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">             <span class="comment">// 显示错误警告信息</span></span><br><span class="line">             <span class="variable language_">this</span>.<span class="property">showWarn</span> = <span class="literal">true</span>;</span><br><span class="line">           &#125;</span><br><span class="line">         &#125;,</span><br></pre></td></tr></table></figure>

<p>判断<code>userInfo</code>中是否有值，如果没有值，展示出错误警告信息。</p>
<p>通过浏览器，进行测试。发现如果用户没有在文本框中输入用户名，直接单击了“新增用户”，这时给出了错误提示的窗口。</p>
<p>但是用户没有关闭错误提示的窗口，而是直接在文本框中输入了用户名，然后又点击了”新增用户”按钮，这时“成功窗口”与“警告窗口”都显示出来了。</p>
<p>下面需要解决这个问题。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;message&quot;</span>, &#123;</span><br><span class="line">  <span class="comment">//show表示的含义，控制弹出窗口的显示与隐藏。</span></span><br><span class="line">  <span class="comment">//slot:表示占坑。也就是窗口中的内容，是通过外部组件传递过来的。</span></span><br><span class="line">  <span class="attr">props</span>: [<span class="string">&quot;show&quot;</span>],</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`&lt;div class=&#x27;message-box&#x27; v-if=&quot;show&quot;&gt;</span></span><br><span class="line"><span class="string">             &lt;!--具名插槽--&gt;</span></span><br><span class="line"><span class="string">             &lt;slot name=&quot;title&quot;&gt;默认标题&lt;/slot&gt;</span></span><br><span class="line"><span class="string">            &lt;slot&gt;&lt;/slot&gt;</span></span><br><span class="line"><span class="string">            &lt;span class=&quot;message-box-close&quot; @click=&#x27;$emit(&quot;close&quot;,false)&#x27;&gt;关闭&lt;/span&gt;</span></span><br><span class="line"><span class="string">          &lt;/div&gt;`</span>,</span><br><span class="line">  <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">//给总线绑定`message-close`事件</span></span><br><span class="line">    <span class="comment">//也就是监听是否有`message-close`事件被触发。</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">$bus</span>.$on(<span class="string">&quot;message-close&quot;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">      <span class="variable language_">this</span>.$emit(<span class="string">&quot;close&quot;</span>, <span class="literal">false</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在<code>message</code>组件加载完后，给事件总线绑定了<code>message-close</code>事件，当该事件触发后还是向父组件发送了<code>close</code>事件，这一点与单击关闭按钮是一样的。</p>
<p>下面，怎样触发总线的<code>message-close</code>事件呢？</p>
<p>我们可以在窗口中添加一个“清空提示栏”按钮，单击该按钮的时候可以触发<code>message-close</code>事件，从而关闭提示窗口。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 清空提示栏 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;toolbar&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;$bus.$emit(&#x27;message-close&#x27;)&quot;</span>&gt;</span>清空提示栏<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>单击”清空提示栏”按钮后，触发事件总线的<code>message-close</code>事件。</p>
<p>最后完善一下<code>closeWindow</code>方法，该方法控制整个提示窗口的关闭</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//关闭窗口</span></span><br><span class="line">        <span class="title function_">closeWindow</span>(<span class="params">data</span>) &#123;</span><br><span class="line">          <span class="variable language_">this</span>.<span class="property">isShow</span> = data;</span><br><span class="line">          <span class="variable language_">this</span>.<span class="property">showWarn</span> = data;</span><br><span class="line">        &#125;,</span><br></pre></td></tr></table></figure>

<p>完整代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>列表渲染<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.actived</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.message-box</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">10px</span> <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.success</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#4fc</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#42b</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.warning</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: red;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#42b</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.message-box-close</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">float</span>: right;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 弹窗组件 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">message</span> <span class="attr">:show</span>=<span class="string">&quot;isShow&quot;</span> @<span class="attr">close</span>=<span class="string">&quot;closeWindow&quot;</span> <span class="attr">class</span>=<span class="string">&quot;success&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- titile的插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:title</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">h2</span>&gt;</span>恭喜<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 默认插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span>&gt;</span> 添加用户成功 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 警告 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">message</span> <span class="attr">:show</span>=<span class="string">&quot;showWarn&quot;</span> @<span class="attr">close</span>=<span class="string">&quot;closeWindow&quot;</span> <span class="attr">class</span>=<span class="string">&quot;warning&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- titile的插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:title</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">h2</span>&gt;</span>警告<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 默认插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span>&gt;</span> 请输入用户名 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 清空提示栏 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;toolbar&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;$bus.$emit(&#x27;message-close&#x27;)&quot;</span>&gt;</span>清空提示栏<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 批量更新身高 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model.number</span>=<span class="string">&quot;height&quot;</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;batchUpdate&quot;</span>&gt;</span>批量更新用户身高<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 新增用户 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-add</span> @<span class="attr">add-user</span>=<span class="string">&quot;addUser&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;userInfo&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-add</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 用户列表组件 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-list</span> <span class="attr">:users</span>=<span class="string">&quot;users&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-list</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>总人数：&#123;&#123;totalCount&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//创建事件总线</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$bus</span> = <span class="keyword">new</span> <span class="title class_">Vue</span>();</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//创建弹出的组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;message&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//show表示的含义，控制弹出窗口的显示与隐藏。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//slot:表示占坑。也就是窗口中的内容，是通过外部组件传递过来的。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;show&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`&lt;div class=&#x27;message-box&#x27; v-if=&quot;show&quot;&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;!--具名插槽--&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;slot name=&quot;title&quot;&gt;默认标题&lt;/slot&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;slot&gt;&lt;/slot&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;span class=&quot;message-box-close&quot; @click=&#x27;$emit(&quot;close&quot;,false)&#x27;&gt;关闭&lt;/span&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">          &lt;/div&gt;`</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//给总线绑定`message-close`事件</span></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//也就是监听是否有`message-close`事件被触发。</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">$bus</span>.$on(<span class="string">&quot;message-close&quot;</span>, <span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.$emit(<span class="string">&quot;close&quot;</span>, <span class="literal">false</span>);</span></span><br><span class="line"><span class="language-javascript">          &#125;);</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//新增用户组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-add&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// data() &#123;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//   return &#123;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//     userInfo: &quot;&quot;,</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//   &#125;;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// &#125;,</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;value&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;input type=&quot;text&quot; :value=&quot;value&quot; @input=&quot;onInput&quot; v-on:keydown.enter=&quot;addUser&quot; /&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;/p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">             &lt;button @click=&quot;addUser&quot;&gt;新增用户&lt;/button&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;/div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            `</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//将输入的用户数据通知给父组件，来完成新增用户操作.</span></span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// this.$emit(&quot;add-user&quot;, this.userInfo);</span></span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.$emit(<span class="string">&quot;add-user&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// this.userInfo = &quot;&quot;;</span></span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">onInput</span>(<span class="params">e</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.$emit(<span class="string">&quot;input&quot;</span>, e.<span class="property">target</span>.<span class="property">value</span>);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 用户列表</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-list&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">type</span>: <span class="title class_">Array</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">default</span>: [],</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">        &lt;div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;p v-if=&quot;users.length===0&quot;&gt;没有任何用户数据&lt;/p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;ul v-else&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;li</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                v-for=&quot;(item,index) in users&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                :key=&quot;item.id&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                :style=&quot;&#123;backgroundColor:selectItem===item?&#x27;#dddddd&#x27;:&#x27;transparent&#x27;&#125;&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                @mousemove=&quot;selectItem=item&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---身高:&#123;&#123;item.height&#125;&#125;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;/li&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;/ul&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">      &lt;/div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">        `</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">num</span>: <span class="number">100</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: [],</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">height</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">userInfo</span>: <span class="string">&quot;abc&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">isShow</span>: <span class="literal">false</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">showWarn</span>: <span class="literal">false</span>, <span class="comment">// 控制警告窗口的显示与隐藏</span></span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//组件实例已创建时</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">async</span> <span class="title function_">created</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">const</span> users = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">getUserList</span>();</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">users</span> = users;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新用户身高</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="title function_">batchUpdate</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//关闭窗口</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">closeWindow</span>(<span class="params">data</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">isShow</span> = data;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">showWarn</span> = data;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//添加用户的信息</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">userInfo</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">push</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">                  <span class="attr">id</span>: <span class="variable language_">this</span>.<span class="property">users</span>[<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> - <span class="number">1</span>].<span class="property">id</span> + <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">                  <span class="attr">name</span>: <span class="variable language_">this</span>.<span class="property">userInfo</span>,</span></span><br><span class="line"><span class="language-javascript">                &#125;);</span></span><br><span class="line"><span class="language-javascript">                <span class="variable language_">this</span>.<span class="property">userInfo</span> = <span class="string">&quot;&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">                <span class="comment">//完成用户添加后，给出相应的提示信息</span></span></span><br><span class="line"><span class="language-javascript">                <span class="variable language_">this</span>.<span class="property">isShow</span> = <span class="literal">true</span>;</span></span><br><span class="line"><span class="language-javascript">              &#125;</span></span><br><span class="line"><span class="language-javascript">            &#125; <span class="keyword">else</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">// 显示错误警告信息</span></span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">showWarn</span> = <span class="literal">true</span>;</span></span><br><span class="line"><span class="language-javascript">            &#125;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新身高，动态的给users中添加身高属性</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   c.height = this.height;</span></span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   Vue.set(c, &quot;height&quot;, this.height);</span></span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.$set(c, <span class="string">&quot;height&quot;</span>, <span class="variable language_">this</span>.<span class="property">height</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getTotal</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;methods&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> + <span class="string">&quot;个&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getUserList</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="title function_">resolve</span>([</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">3</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;老王&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                ]);</span></span><br><span class="line"><span class="language-javascript">              &#125;, <span class="number">2000</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">watch</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="comment">//立即执行</span></span></span><br><span class="line"><span class="language-javascript">            <span class="title function_">handler</span>(<span class="params">newValue, oldValue</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">totalCount</span> = newValue.<span class="property">length</span> + <span class="string">&quot;个人&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="16-4-vm-once与vm-off"><a href="#16-4-vm-once与vm-off" class="headerlink" title="16.4 vm.$once与vm.$off"></a>16.4 <code>vm.$once</code>与<code>vm.$off</code></h3><p>关于这两个方法，大家只需要了解一下就可以了。</p>
<p><code>vm.$once</code><br>监听一个自定义事件，但是只触发一次。一旦触发之后，监听器就会被移除。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">vm.$on(<span class="string">&quot;test&quot;</span>, <span class="keyword">function</span> (<span class="params">msg</span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(msg);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p><code>vm.$off</code></p>
<p>移除自定义事件监听器。</p>
<ul>
<li><p>如果没有提供参数，则移除所有的事件监听器；</p>
</li>
<li><p>如果只提供了事件，则移除该事件所有的监听器；</p>
</li>
<li><p>如果同时提供了事件与回调，则只移除这个回调的监听器</p>
</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">vm.$off() // 移除所有的事件监听器</span><br><span class="line">vm.$off(&#x27;test&#x27;) // 移除该事件所有的监听器</span><br><span class="line">vm.$off(&#x27;test&#x27;, callback) // 只移除这个回调的监听器</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="16-5-ref-和vm-refs"><a href="#16-5-ref-和vm-refs" class="headerlink" title="16.5 ref 和vm.$refs"></a>16.5 <code>ref</code> 和<code>vm.$refs</code></h3><p><code>ref</code>被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的<code>$refs</code>对象上，如果在普通的<code>DOM</code>元素上使用，引用指向的就是<code>DOM</code>元素;如果用在子组件上，引用就指向组件的实例。</p>
<p>如下代码示例，是用来设置输入框的焦点</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&lt;input type=<span class="string">&quot;text&quot;</span>  ref=<span class="string">&quot;inp&quot;</span> /&gt;</span><br><span class="line"><span class="title function_">mounted</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="comment">//mounted之后才能访问到inp</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">inp</span>.<span class="title function_">focus</span>()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>下面在用户管理案例中，看一下具体的实现效果。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//新增用户组件</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-add&quot;</span>, &#123;</span><br><span class="line">  <span class="comment">// data() &#123;</span></span><br><span class="line">  <span class="comment">//   return &#123;</span></span><br><span class="line">  <span class="comment">//     userInfo: &quot;&quot;,</span></span><br><span class="line">  <span class="comment">//   &#125;;</span></span><br><span class="line">  <span class="comment">// &#125;,</span></span><br><span class="line">  <span class="attr">props</span>: [<span class="string">&quot;value&quot;</span>],</span><br><span class="line">  <span class="attr">template</span>: <span class="string">`</span></span><br><span class="line"><span class="string">              &lt;div&gt;</span></span><br><span class="line"><span class="string">               &lt;p&gt;</span></span><br><span class="line"><span class="string">                  &lt;input type=&quot;text&quot; :value=&quot;value&quot; @input=&quot;onInput&quot; v-on:keydown.enter=&quot;addUser&quot; ref=&quot;inp&quot; /&gt;</span></span><br><span class="line"><span class="string">               &lt;/p&gt;</span></span><br><span class="line"><span class="string">               &lt;button @click=&quot;addUser&quot;&gt;新增用户&lt;/button&gt;</span></span><br><span class="line"><span class="string">                &lt;/div&gt;</span></span><br><span class="line"><span class="string">              `</span>,</span><br><span class="line"></span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="comment">//将输入的用户数据通知给父组件，来完成新增用户操作.</span></span><br><span class="line">      <span class="comment">// this.$emit(&quot;add-user&quot;, this.userInfo);</span></span><br><span class="line">      <span class="variable language_">this</span>.$emit(<span class="string">&quot;add-user&quot;</span>);</span><br><span class="line">      <span class="comment">// this.userInfo = &quot;&quot;;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">onInput</span>(<span class="params">e</span>) &#123;</span><br><span class="line">      <span class="variable language_">this</span>.$emit(<span class="string">&quot;input&quot;</span>, e.<span class="property">target</span>.<span class="property">value</span>);</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">inp</span>.<span class="title function_">focus</span>();</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们首先给<code>user-add</code>组件模板中的文本框添加了<code>ref</code>属性。</p>
<p>然后，在其所对应的<code>mounted</code>方法中，通过<code>$refs</code>找到文本框，然后为其添加焦点。</p>
<p>回到浏览器中，刷新浏览器，可以看到对应的文本框获取了焦点。</p>
<p>下面，我们在将弹出窗口修改一下：</p>
<p>下面修改一下<code>message</code>模板中的内容。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//创建弹出的组件</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;message&quot;</span>, &#123;</span><br><span class="line">  <span class="comment">//show表示的含义，控制弹出窗口的显示与隐藏。</span></span><br><span class="line">  <span class="comment">//slot:表示占坑。也就是窗口中的内容，是通过外部组件传递过来的。</span></span><br><span class="line">  <span class="comment">// props: [&quot;show&quot;],</span></span><br><span class="line">  <span class="title function_">data</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      <span class="attr">show</span>: <span class="literal">false</span>,</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="attr">template</span>: <span class="string">`&lt;div class=&#x27;message-box&#x27; v-if=&quot;show&quot;&gt;</span></span><br><span class="line"><span class="string">               &lt;!--具名插槽--&gt;</span></span><br><span class="line"><span class="string">               &lt;slot name=&quot;title&quot;&gt;默认标题&lt;/slot&gt;</span></span><br><span class="line"><span class="string">              &lt;slot&gt;&lt;/slot&gt;</span></span><br><span class="line"><span class="string">              &lt;span class=&quot;message-box-close&quot; @click=&#x27;toggle&#x27;&gt;关闭&lt;/span&gt;</span></span><br><span class="line"><span class="string">            &lt;/div&gt;`</span>,</span><br><span class="line">  <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">//给总线绑定`message-close`事件</span></span><br><span class="line">    <span class="comment">//也就是监听是否有`message-close`事件被触发。</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">$bus</span>.$on(<span class="string">&quot;message-close&quot;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// this.$emit(&quot;close&quot;, false);</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="title function_">toggle</span>();</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="title function_">toggle</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">show</span> = !<span class="variable language_">this</span>.<span class="property">show</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，取消了<code>props</code>，而定义了<code>data</code>属性，表明的含义就是整个窗口的状态的控制，也就是提示窗口的显示与隐藏，都是有自己控制，而不是受外部传递的参数来进行控制了。</p>
<p>同时，在该组件中，添加了<code>toggle</code>方法，修改对应的<code>show</code>的状态。</p>
<p>所以模板中，按钮的单击事件触发以后，调用的就是<code>toggle</code>方法，也就是单击了窗口的右侧的关闭按钮，是通过调用<code>toggle</code>方法来完成，窗口的关闭。</p>
<p>同样事件<code>message-close</code>触发以后，也是调用<code>toggle</code>方法来关闭窗口。</p>
<p>下面看一下关于<code>message</code>模板的使用。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 弹窗组件 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">message</span> <span class="attr">ref</span>=<span class="string">&quot;msgSuccess&quot;</span> <span class="attr">class</span>=<span class="string">&quot;success&quot;</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- titile的插槽 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h2</span>&gt;</span>恭喜<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- 默认插槽 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">template</span>&gt;</span> 添加用户成功 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们为<code>message</code>组件，添加了<code>ref</code>属性。</p>
<p>同理表示警告的窗口，也需要添加<code>ref</code>的属性。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 警告 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">message</span> <span class="attr">ref</span>=<span class="string">&quot;msgWaring&quot;</span> <span class="attr">class</span>=<span class="string">&quot;warning&quot;</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- titile的插槽 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h2</span>&gt;</span>警告<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="comment">&lt;!-- 默认插槽 --&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">template</span>&gt;</span> 请输入用户名 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>关于<code>data</code>中定义的<code>isShow</code>与<code>showWarn</code>就可以取消了。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">data</span>: &#123;</span><br><span class="line">          <span class="attr">num</span>: <span class="number">100</span>,</span><br><span class="line">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span><br><span class="line">          <span class="attr">users</span>: [],</span><br><span class="line">          <span class="attr">height</span>: <span class="number">0</span>,</span><br><span class="line">          <span class="attr">userInfo</span>: <span class="string">&quot;abc&quot;</span>,</span><br><span class="line">          <span class="comment">// isShow: false,</span></span><br><span class="line">          <span class="comment">// showWarn: false, // 控制警告窗口的显示与隐藏</span></span><br><span class="line">        &#125;,</span><br></pre></td></tr></table></figure>

<p>当用户点击“新增用户”按钮的时候，执行<code>addUser</code>方法，下面也需要对该方法进行如下修改：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//添加用户的信息</span></span><br><span class="line">         <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span><br><span class="line">           <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">userInfo</span>) &#123;</span><br><span class="line">             <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">               <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">push</span>(&#123;</span><br><span class="line">                 <span class="attr">id</span>: <span class="variable language_">this</span>.<span class="property">users</span>[<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> - <span class="number">1</span>].<span class="property">id</span> + <span class="number">1</span>,</span><br><span class="line">                 <span class="attr">name</span>: <span class="variable language_">this</span>.<span class="property">userInfo</span>,</span><br><span class="line">               &#125;);</span><br><span class="line">               <span class="variable language_">this</span>.<span class="property">userInfo</span> = <span class="string">&quot;&quot;</span>;</span><br><span class="line">               <span class="comment">//完成用户添加后，给出相应的提示信息</span></span><br><span class="line">               <span class="comment">// this.isShow = true;</span></span><br><span class="line">               <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">msgSuccess</span>.<span class="title function_">toggle</span>();</span><br><span class="line">             &#125;</span><br><span class="line">           &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">             <span class="comment">// 显示错误警告信息</span></span><br><span class="line">             <span class="comment">// this.showWarn = true;</span></span><br><span class="line">             <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">msgWaring</span>.<span class="title function_">toggle</span>();</span><br><span class="line">           &#125;</span><br><span class="line">         &#125;,</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们都是通过<code>$ref</code> 找到对应的窗口，然后调用<code>toggle</code>方法，来修改对应的状态。</p>
<p>因为，我们前面讲过如果<code>ref</code>用在子组件上，引用就指向组件的实例.所以可以调用组件内部的<code>toggle</code>方法。</p>
<p>完整代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>列表渲染<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.actived</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.message-box</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">10px</span> <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.success</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#4fc</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#42b</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.warning</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: red;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#42b</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.message-box-close</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">float</span>: right;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 弹窗组件 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">message</span> <span class="attr">ref</span>=<span class="string">&quot;msgSuccess&quot;</span> <span class="attr">class</span>=<span class="string">&quot;success&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- titile的插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:title</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">h2</span>&gt;</span>恭喜<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 默认插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span>&gt;</span> 添加用户成功 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 警告 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">message</span> <span class="attr">ref</span>=<span class="string">&quot;msgWaring&quot;</span> <span class="attr">class</span>=<span class="string">&quot;warning&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- titile的插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:title</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">h2</span>&gt;</span>警告<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 默认插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span>&gt;</span> 请输入用户名 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 清空提示栏 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;toolbar&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;$bus.$emit(&#x27;message-close&#x27;)&quot;</span>&gt;</span>清空提示栏<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 批量更新身高 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model.number</span>=<span class="string">&quot;height&quot;</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;batchUpdate&quot;</span>&gt;</span>批量更新用户身高<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 新增用户 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-add</span> @<span class="attr">add-user</span>=<span class="string">&quot;addUser&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;userInfo&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-add</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 用户列表组件 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-list</span> <span class="attr">:users</span>=<span class="string">&quot;users&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-list</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>总人数：&#123;&#123;totalCount&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//创建事件总线</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$bus</span> = <span class="keyword">new</span> <span class="title class_">Vue</span>();</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//创建弹出的组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;message&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//show表示的含义，控制弹出窗口的显示与隐藏。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//slot:表示占坑。也就是窗口中的内容，是通过外部组件传递过来的。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// props: [&quot;show&quot;],</span></span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">show</span>: <span class="literal">false</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`&lt;div class=&#x27;message-box&#x27; v-if=&quot;show&quot;&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">               &lt;!--具名插槽--&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">               &lt;slot name=&quot;title&quot;&gt;默认标题&lt;/slot&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;slot&gt;&lt;/slot&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;span class=&quot;message-box-close&quot; @click=&#x27;toggle&#x27;&gt;关闭&lt;/span&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;/div&gt;`</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//给总线绑定`message-close`事件</span></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//也就是监听是否有`message-close`事件被触发。</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">$bus</span>.$on(<span class="string">&quot;message-close&quot;</span>, <span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// this.$emit(&quot;close&quot;, false);</span></span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//当警告窗口和提示信息的窗口，展示出来了才关闭。</span></span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">show</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="title function_">toggle</span>();</span></span><br><span class="line"><span class="language-javascript">            &#125;</span></span><br><span class="line"><span class="language-javascript">          &#125;);</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">toggle</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">show</span> = !<span class="variable language_">this</span>.<span class="property">show</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//新增用户组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-add&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// data() &#123;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//   return &#123;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//     userInfo: &quot;&quot;,</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//   &#125;;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// &#125;,</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;value&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">               &lt;p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  &lt;input type=&quot;text&quot; :value=&quot;value&quot; @input=&quot;onInput&quot; v-on:keydown.enter=&quot;addUser&quot; ref=&quot;inp&quot; /&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">               &lt;/p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">               &lt;button @click=&quot;addUser&quot;&gt;新增用户&lt;/button&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;/div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              `</span>,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//将输入的用户数据通知给父组件，来完成新增用户操作.</span></span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// this.$emit(&quot;add-user&quot;, this.userInfo);</span></span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.$emit(<span class="string">&quot;add-user&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// this.userInfo = &quot;&quot;;</span></span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">onInput</span>(<span class="params">e</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.$emit(<span class="string">&quot;input&quot;</span>, e.<span class="property">target</span>.<span class="property">value</span>);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">inp</span>.<span class="title function_">focus</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 用户列表</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-list&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">type</span>: <span class="title class_">Array</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">default</span>: [],</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">          &lt;div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  &lt;p v-if=&quot;users.length===0&quot;&gt;没有任何用户数据&lt;/p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;ul v-else&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  &lt;li</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  v-for=&quot;(item,index) in users&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  :key=&quot;item.id&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  :style=&quot;&#123;backgroundColor:selectItem===item?&#x27;#dddddd&#x27;:&#x27;transparent&#x27;&#125;&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  @mousemove=&quot;selectItem=item&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  &gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---身高:&#123;&#123;item.height&#125;&#125;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  &lt;/li&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;/ul&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">        &lt;/div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">          `</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">num</span>: <span class="number">100</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: [],</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">height</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">userInfo</span>: <span class="string">&quot;abc&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">// isShow: false,</span></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">// showWarn: false, // 控制警告窗口的显示与隐藏</span></span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//组件实例已创建时</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">async</span> <span class="title function_">created</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">const</span> users = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">getUserList</span>();</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">users</span> = users;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新用户身高</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="title function_">batchUpdate</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//关闭窗口</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">closeWindow</span>(<span class="params">data</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">isShow</span> = data;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">showWarn</span> = data;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//添加用户的信息</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">userInfo</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">push</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">                  <span class="attr">id</span>: <span class="variable language_">this</span>.<span class="property">users</span>[<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> - <span class="number">1</span>].<span class="property">id</span> + <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">                  <span class="attr">name</span>: <span class="variable language_">this</span>.<span class="property">userInfo</span>,</span></span><br><span class="line"><span class="language-javascript">                &#125;);</span></span><br><span class="line"><span class="language-javascript">                <span class="variable language_">this</span>.<span class="property">userInfo</span> = <span class="string">&quot;&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">                <span class="comment">//完成用户添加后，给出相应的提示信息</span></span></span><br><span class="line"><span class="language-javascript">                <span class="comment">// this.isShow = true;</span></span></span><br><span class="line"><span class="language-javascript">                <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">msgSuccess</span>.<span class="title function_">toggle</span>();</span></span><br><span class="line"><span class="language-javascript">              &#125;</span></span><br><span class="line"><span class="language-javascript">            &#125; <span class="keyword">else</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">// 显示错误警告信息</span></span></span><br><span class="line"><span class="language-javascript">              <span class="comment">// this.showWarn = true;</span></span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">msgWaring</span>.<span class="title function_">toggle</span>();</span></span><br><span class="line"><span class="language-javascript">            &#125;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新身高，动态的给users中添加身高属性</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   c.height = this.height;</span></span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   Vue.set(c, &quot;height&quot;, this.height);</span></span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.$set(c, <span class="string">&quot;height&quot;</span>, <span class="variable language_">this</span>.<span class="property">height</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getTotal</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;methods&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> + <span class="string">&quot;个&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getUserList</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="title function_">resolve</span>([</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">3</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;老王&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                ]);</span></span><br><span class="line"><span class="language-javascript">              &#125;, <span class="number">2000</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">watch</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="comment">//立即执行</span></span></span><br><span class="line"><span class="language-javascript">            <span class="title function_">handler</span>(<span class="params">newValue, oldValue</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">totalCount</span> = newValue.<span class="property">length</span> + <span class="string">&quot;个人&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>下面在对<code>ref</code>与<code>vm.$refs</code>的使用做一个总结：</p>
<ul>
<li><code>ref</code>是作为渲染结果被创建的，在初始渲染时不能访问它们。也就是必须在<code>mounted</code>构造函数中。</li>
<li><code>$refs</code>不是响应式的，不要试图用它在模板中做数据绑定。</li>
</ul>
<h2 id="17、过滤器"><a href="#17、过滤器" class="headerlink" title="17、过滤器"></a>17、过滤器</h2><h3 id="17-1-过滤器基本使用"><a href="#17-1-过滤器基本使用" class="headerlink" title="17.1 过滤器基本使用"></a>17.1 过滤器基本使用</h3><p>过滤器在日常生活中也是比较常见的，例如自来水的过滤等。</p>
<p>在<code>Vue</code>中，过滤器的作用就是格式化数据，也就是对数据的过滤处理，比如将字符串格式化为首字母大写</p>
<p>或者将日期格式化为指定的格式等。</p>
<p>下面先看一下自定义过滤器的语法</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Vue.filter(&#x27;过滤器名称&#x27;,function(value)&#123;</span><br><span class="line">//value参数表示要处理的数据</span><br><span class="line">  //过滤器业务逻辑，最终将处理后的数据进行返回</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>定义好以后可以使用。使用的方式如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;div&gt;&#123;&#123;msg|upper&#125;&#125;&lt;/div&gt;</span><br><span class="line">&lt;div&gt;&#123;&#123;msg|upper|lower&#125;&#125;&lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>具体的程序如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>过滤器基本使用<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;msg&quot;</span> /&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!--使用过滤器--&gt;</span></span><br><span class="line">        &#123;&#123;msg|upper&#125;&#125;</span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//定义过滤器，让输入的单词首字母变成大写.</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">filter</span>(<span class="string">&quot;upper&quot;</span>, <span class="keyword">function</span> (<span class="params">value</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//获取首字母让其转换成大写，然后拼接后面的内容。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">return</span> value.<span class="title function_">charAt</span>(<span class="number">0</span>).<span class="title function_">toUpperCase</span>() + value.<span class="title function_">slice</span>(<span class="number">0</span>);</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">msg</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>过滤器在使用的时候，可以采用如下的方式：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;div&gt;&#123;&#123;msg|upper|lower&#125;&#125;&lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>也就是，先对<code>msg</code>中的数据使用<code>upper</code>过滤器，得到的结果在交给<code>lower</code>过滤器进行处理。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>过滤器基本使用<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;msg&quot;</span> /&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span>&gt;</span>&#123;&#123;msg|upper&#125;&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span>&gt;</span>&#123;&#123;msg|upper|lower&#125;&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//定义过滤器，让输入的单词首字母变成大写.</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">filter</span>(<span class="string">&quot;upper&quot;</span>, <span class="keyword">function</span> (<span class="params">value</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//获取首字母让其转换成大写，然后拼接后面的内容。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">return</span> value.<span class="title function_">charAt</span>(<span class="number">0</span>).<span class="title function_">toUpperCase</span>() + value.<span class="title function_">slice</span>(<span class="number">0</span>);</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">filter</span>(<span class="string">&quot;lower&quot;</span>, <span class="keyword">function</span> (<span class="params">value</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">return</span> value.<span class="title function_">charAt</span>(<span class="number">0</span>).<span class="title function_">toLowerCase</span>() + value.<span class="title function_">slice</span>(<span class="number">0</span>);</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">msg</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>上面定义的顾虑器是全局的过滤器，当然也可以定义局部过滤器。</p>
<p>局部过滤器只能在其所定义的组件内使用。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>过滤器基本使用<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;msg&quot;</span> /&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span>&gt;</span>&#123;&#123;msg|upper&#125;&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span>&gt;</span>&#123;&#123;msg|upper|lower&#125;&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//定义过滤器，让输入的单词首字母变成大写.</span></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//   Vue.filter(&quot;upper&quot;, function (value) &#123;</span></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//     //获取首字母让其转换成大写，然后拼接后面的内容。</span></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//     return value.charAt(0).toUpperCase() + value.slice(0);</span></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//   &#125;);</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">filter</span>(<span class="string">&quot;lower&quot;</span>, <span class="keyword">function</span> (<span class="params">value</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">return</span> value.<span class="title function_">charAt</span>(<span class="number">0</span>).<span class="title function_">toLowerCase</span>() + value.<span class="title function_">slice</span>(<span class="number">0</span>);</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">msg</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//局部过滤器</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">filters</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">upper</span>: <span class="keyword">function</span> (<span class="params">value</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> value.<span class="title function_">charAt</span>(<span class="number">0</span>).<span class="title function_">toUpperCase</span>() + value.<span class="title function_">slice</span>(<span class="number">0</span>);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们通过<code>fileters</code>定义了一个局部的过滤器<code>upper</code>.</p>
<p>在前面，我们也说过<code>Vue</code>实例本身就是一个组件。</p>
<h3 id="17-2-带参数的过滤器"><a href="#17-2-带参数的过滤器" class="headerlink" title="17.2 带参数的过滤器"></a>17.2 带参数的过滤器</h3><p>带参数的过滤器定义如下：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">Vue.filter(&#x27;format&#x27;,function(value,arg1)&#123;</span><br><span class="line">	//value表示要过滤的数据。</span><br><span class="line">	//arg1,表示传递过来的参数</span><br><span class="line"></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>使用的方式如下</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;div&gt;</span><br><span class="line"> &#123;&#123;data|format(`yyyy-MM-dd`)&#125;&#125;</span><br><span class="line">&lt;/div&gt;</span><br></pre></td></tr></table></figure>

<p>要处理的数据<code>data</code>交给了过滤器中回调函数的<code>value</code>参数，<code>yyyy-MM-dd</code>交给了<code>arg1</code>.</p>
<p>如下代码：</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot; /&gt;</span><br><span class="line">    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</span><br><span class="line">    &lt;title&gt;过滤器参数&lt;/title&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">    &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">      &lt;div&gt;</span><br><span class="line">        &#123;&#123; date | format(&quot;abc&quot;, &quot;hello&quot;) &#125;&#125;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">    &lt;script src=&quot;vue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;script&gt;</span><br><span class="line">      Vue.filter(&quot;format&quot;, function (value, arg, arg1) &#123;</span><br><span class="line">        console.log(arg, arg1);</span><br><span class="line">        return value;</span><br><span class="line">      &#125;);</span><br><span class="line">      const vm = new Vue(&#123;</span><br><span class="line">        el: &quot;#app&quot;,</span><br><span class="line">        data: &#123;</span><br><span class="line">          date: new Date(),</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;);</span><br><span class="line">    &lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们定义了<code>format</code>过滤器，然后在使用的时候，我们是将<code>date</code>日期数据给了<code>value</code></p>
<p><code>abc</code>这个字符串给了<code>arg</code>,<code>hello</code>给了<code>arg1</code>.</p>
<p>下面，我们把日期给具体的处理一下</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>过滤器参数<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span>&gt;</span>&#123;&#123;date|format(&#x27;yyyy-MM-dd&#x27;)&#125;&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">filter</span>(<span class="string">&quot;format&quot;</span>, <span class="keyword">function</span> (<span class="params">value, arg, arg1</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">let</span> result = <span class="string">&quot;&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">        result +=</span></span><br><span class="line"><span class="language-javascript">          value.<span class="title function_">getFullYear</span>() +</span></span><br><span class="line"><span class="language-javascript">          <span class="string">&quot;-&quot;</span> +</span></span><br><span class="line"><span class="language-javascript">          (value.<span class="title function_">getMonth</span>() + <span class="number">1</span>) +</span></span><br><span class="line"><span class="language-javascript">          <span class="string">&quot;-&quot;</span> +</span></span><br><span class="line"><span class="language-javascript">          value.<span class="title function_">getDate</span>();</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">return</span> result;</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">date</span>: <span class="keyword">new</span> <span class="title class_">Date</span>(),</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="18、自定义指令"><a href="#18、自定义指令" class="headerlink" title="18、自定义指令"></a>18、自定义指令</h2><h3 id="18-1-自定义指令基本用法"><a href="#18-1-自定义指令基本用法" class="headerlink" title="18.1 自定义指令基本用法"></a>18.1 自定义指令基本用法</h3><p>为什么需要自定义指令呢？</p>
<p>因为内置指令不满足需求。</p>
<p>下面看一下基本的创建自定义指令语法:</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">directive</span>(<span class="string">&quot;focus&quot;</span>, &#123;</span><br><span class="line">  <span class="attr">inserted</span>: <span class="keyword">function</span> (<span class="params">el</span>) &#123;</span><br><span class="line">    <span class="comment">//获取元素焦点</span></span><br><span class="line">    el.<span class="title function_">focus</span>();</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>自定义指令用法</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&lt;input type=<span class="string">&quot;text&quot;</span> v-focus&gt;</span><br></pre></td></tr></table></figure>

<p>下面看一下具体的代码。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>自定义指令基本使用<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-focus</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">directive</span>(<span class="string">&quot;focus&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">inserted</span>: <span class="keyword">function</span> (<span class="params">el</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//el:表示指令所绑定的元素</span></span></span><br><span class="line"><span class="language-javascript">          el.<span class="title function_">focus</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;&#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们通过<code>directive</code>方法创建了一个<code>focus</code>指令。</p>
<p>在使用该指令的时候，一定要加上<code>v-</code>的形式。</p>
<p><code>inserted</code>表示的是指令的钩子函数，含义是：被绑定元素插入父节点时调用。</p>
<h3 id="18-2-自定义指令-带参数"><a href="#18-2-自定义指令-带参数" class="headerlink" title="18.2 自定义指令-带参数"></a>18.2 自定义指令-带参数</h3><p>带参数的自定义指令创建的语法（改变元素背景色）</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">Vue</span>.<span class="title function_">directive</span>(<span class="string">&quot;color&quot;</span>, &#123;</span><br><span class="line">  <span class="attr">inserted</span>: <span class="keyword">function</span> (<span class="params">el, binding</span>) &#123;</span><br><span class="line">    <span class="comment">//binding表示传递过来的参数</span></span><br><span class="line">    el.<span class="property">style</span>.<span class="property">backgroundColor</span> = binding.<span class="property">value</span>.<span class="property">color</span>;</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>指令的用法</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-color</span>=<span class="string">&#x27;&#123;color:&quot;orange&quot;&#125;&#x27;</span> /&gt;</span></span><br></pre></td></tr></table></figure>

<p>下面，看一下完整的代码案例：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>自定义指令带参数<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-color</span>=<span class="string">&quot;msg&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//自定义指令-带参数</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">directive</span>(<span class="string">&quot;color&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">bind</span>: <span class="keyword">function</span> (<span class="params">el, binding</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          el.<span class="property">style</span>.<span class="property">backgroundColor</span> = binding.<span class="property">value</span>.<span class="property">color</span>;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">msg</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">color</span>: <span class="string">&quot;blue&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>通过上面的代码，可以看到定义了一个<code>color</code>的指令，在使用的时候传递了<code>msg</code>对象。</p>
<p>所以这个对象会给<code>binding</code>这个参数，我们通过这个参数的<code>value</code> 属性获取<code>msg</code>对象中的<code>color</code>属性的值，然后用来设置文本框的背景色。</p>
<p>这里使用了<code>bind</code>这个钩子函数：只调用一次，第一次绑定指令到元素时调用，我们可以在此绑定只执行一次的初始化动作。</p>
<h3 id="18-3-自定义局部指令"><a href="#18-3-自定义局部指令" class="headerlink" title="18.3 自定义局部指令"></a>18.3 自定义局部指令</h3><p>局部指令的基本语法：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">directives</span>:&#123;</span><br><span class="line">    <span class="attr">focus</span>:&#123;</span><br><span class="line">        <span class="comment">//指令的定义</span></span><br><span class="line">        <span class="attr">inserted</span>:<span class="keyword">function</span>(<span class="params">el</span>)&#123;</span><br><span class="line">            el.<span class="title function_">focus</span>()</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在<code>Vue</code>实例中添加<code>directives</code></p>
<p>具体实现的代码如下：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>局部指令<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-color</span>=<span class="string">&quot;msg&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> vm = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">msg</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">color</span>: <span class="string">&quot;red&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">directives</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">color</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">bind</span>: <span class="keyword">function</span> (<span class="params">el, binding</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              el.<span class="property">style</span>.<span class="property">backgroundColor</span> = binding.<span class="property">value</span>.<span class="property">color</span>;</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>局部指令只在所定义的组件中使用。</p>
<h2 id="19、渲染函数"><a href="#19、渲染函数" class="headerlink" title="19、渲染函数"></a>19、渲染函数</h2><p><code>Vue</code>推荐在绝大数情况下使用模板来创建你的<code>HTML</code>。然后在一些场景中，你真的需要<code>JavaScript</code>的完全编程的能力，也就是使用<code>javaScript来创建HTML</code>，这时你可以用渲染函数，它比模板更接近编译器。</p>
<p>这里我们先来做一个基本的了解，为后期的深入学习打好一个基础。</p>
<p>下面先看一下<code>render</code>函数的基本结构。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">render</span>:<span class="keyword">function</span>(<span class="params">createElement</span>)&#123;</span><br><span class="line">    <span class="comment">//createElement函数返回的结果为VNode. VNode就是虚拟dom，用js对象来模拟真实的DOM.</span></span><br><span class="line">    retrun <span class="title function_">createElement</span>(</span><br><span class="line">      tag, <span class="comment">//标签名称</span></span><br><span class="line">       data,<span class="comment">// 传递数据</span></span><br><span class="line">       children <span class="comment">//子节点数组</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>下面我们在用户管理这个案例中，使用<code>render</code>函数来创建一个组件。</p>
<p>具体的代码如下：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// heading组件</span></span><br><span class="line"><span class="comment">//&lt;heading :level=&quot;1&quot;&gt;&#123;&#123;title&#125;&#125;&lt;/heading&gt; //这时要创建的组件</span></span><br><span class="line"><span class="comment">// &lt;h2 title=&quot;&quot;&gt;&lt;/h2&gt; //这时上面的组件最终渲染的结果</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;heading&quot;</span>, &#123;</span><br><span class="line">  <span class="attr">props</span>: &#123;</span><br><span class="line">    <span class="attr">level</span>: &#123;</span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">String</span>,</span><br><span class="line">      <span class="attr">required</span>: <span class="literal">true</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span><br><span class="line">    <span class="comment">//h 就是createElement函数</span></span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">h</span>(</span><br><span class="line">      <span class="string">&quot;h&quot;</span> + <span class="variable language_">this</span>.<span class="property">level</span>, <span class="comment">//参数1，表示要创建的元素</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$slots</span>.<span class="property">default</span> <span class="comment">//参数3，子节点VNode数组。（这里没有使用参数2，&#123;&#123;tile&#125;&#125;就是一个子元素）</span></span><br><span class="line">    );</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>接下来就可以使用<code>heading</code>组件了。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 使用render函数创建的头部组件 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">heading</span> <span class="attr">level</span>=<span class="string">&quot;1&quot;</span>&gt;</span> &#123;&#123;title&#125;&#125; <span class="tag">&lt;/<span class="name">heading</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>当然，这里需要在<code>data</code>中定义<code>title</code>属性。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">data</span>: &#123;</span><br><span class="line">          <span class="attr">num</span>: <span class="number">100</span>,</span><br><span class="line">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span><br><span class="line">          <span class="attr">users</span>: [],</span><br><span class="line">          <span class="attr">height</span>: <span class="number">0</span>,</span><br><span class="line">          <span class="attr">userInfo</span>: <span class="string">&quot;abc&quot;</span>,</span><br><span class="line">          <span class="attr">title</span>: <span class="string">&quot;用户管理&quot;</span>,</span><br><span class="line">          <span class="comment">// isShow: false,</span></span><br><span class="line">          <span class="comment">// showWarn: false, // 控制警告窗口的显示与隐藏</span></span><br><span class="line">        &#125;,</span><br></pre></td></tr></table></figure>

<p>完整代码如下（24、<code>render函数.html</code>）：</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>列表渲染<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.actived</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#dddddd</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.message-box</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">padding</span>: <span class="number">10px</span> <span class="number">20px</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.success</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: <span class="number">#4fc</span>;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#42b</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.warning</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">background-color</span>: red;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#42b</span>;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">      <span class="selector-class">.message-box-close</span> &#123;</span></span><br><span class="line"><span class="language-css">        <span class="attribute">float</span>: right;</span></span><br><span class="line"><span class="language-css">      &#125;</span></span><br><span class="line"><span class="language-css">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 弹窗组件 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">message</span> <span class="attr">ref</span>=<span class="string">&quot;msgSuccess&quot;</span> <span class="attr">class</span>=<span class="string">&quot;success&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- titile的插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:title</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">h2</span>&gt;</span>恭喜<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 默认插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span>&gt;</span> 添加用户成功 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 警告 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">message</span> <span class="attr">ref</span>=<span class="string">&quot;msgWaring&quot;</span> <span class="attr">class</span>=<span class="string">&quot;warning&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- titile的插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span> <span class="attr">v-slot:title</span>&gt;</span></span><br><span class="line">          <span class="tag">&lt;<span class="name">h2</span>&gt;</span>警告<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 默认插槽 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">template</span>&gt;</span> 请输入用户名 <span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">message</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">&lt;!-- 使用render函数创建的头部组件 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">heading</span> <span class="attr">level</span>=<span class="string">&quot;1&quot;</span>&gt;</span> &#123;&#123;title&#125;&#125; <span class="tag">&lt;/<span class="name">heading</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 清空提示栏 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;toolbar&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;$bus.$emit(&#x27;message-close&#x27;)&quot;</span>&gt;</span>清空提示栏<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 批量更新身高 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model.number</span>=<span class="string">&quot;height&quot;</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;batchUpdate&quot;</span>&gt;</span>批量更新用户身高<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 新增用户 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-add</span> @<span class="attr">add-user</span>=<span class="string">&quot;addUser&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;userInfo&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-add</span>&gt;</span></span><br><span class="line">      <span class="comment">&lt;!-- 用户列表组件 --&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">user-list</span> <span class="attr">:users</span>=<span class="string">&quot;users&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">user-list</span>&gt;</span></span><br><span class="line"></span><br><span class="line">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>总人数：&#123;&#123;totalCount&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;vue.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//创建事件总线</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$bus</span> = <span class="keyword">new</span> <span class="title class_">Vue</span>();</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// heading组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//&lt;heading :level=&quot;1&quot;&gt;&#123;&#123;title&#125;&#125;&lt;/heading&gt; //这时要创建的组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// &lt;h2 title=&quot;&quot;&gt;&lt;/h2&gt; //这时上面的组件最终渲染的结果</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;heading&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">level</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">type</span>: <span class="title class_">String</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">required</span>: <span class="literal">true</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> <span class="title function_">h</span>(</span></span><br><span class="line"><span class="language-javascript">            <span class="string">&quot;h&quot;</span> + <span class="variable language_">this</span>.<span class="property">level</span>, <span class="comment">//参数1，表示要创建的元素</span></span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">$slots</span>.<span class="property">default</span> <span class="comment">//参数3，子节点VNode数组。（这里没有使用参数2，&#123;&#123;tile&#125;&#125;就是一个子元素）</span></span></span><br><span class="line"><span class="language-javascript">          );</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//创建弹出的组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;message&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//show表示的含义，控制弹出窗口的显示与隐藏。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//slot:表示占坑。也就是窗口中的内容，是通过外部组件传递过来的。</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// props: [&quot;show&quot;],</span></span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">show</span>: <span class="literal">false</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`&lt;div class=&#x27;message-box&#x27; v-if=&quot;show&quot;&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">               &lt;!--具名插槽--&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">               &lt;slot name=&quot;title&quot;&gt;默认标题&lt;/slot&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;slot&gt;&lt;/slot&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;span class=&quot;message-box-close&quot; @click=&#x27;toggle&#x27;&gt;关闭&lt;/span&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">            &lt;/div&gt;`</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//给总线绑定`message-close`事件</span></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//也就是监听是否有`message-close`事件被触发。</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">$bus</span>.$on(<span class="string">&quot;message-close&quot;</span>, <span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// this.$emit(&quot;close&quot;, false);</span></span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//当警告窗口和提示信息的窗口，展示出来了才关闭。</span></span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">show</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="title function_">toggle</span>();</span></span><br><span class="line"><span class="language-javascript">            &#125;</span></span><br><span class="line"><span class="language-javascript">          &#125;);</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">toggle</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">show</span> = !<span class="variable language_">this</span>.<span class="property">show</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">//新增用户组件</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-add&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// data() &#123;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//   return &#123;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//     userInfo: &quot;&quot;,</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//   &#125;;</span></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// &#125;,</span></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: [<span class="string">&quot;value&quot;</span>],</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">               &lt;p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  &lt;input type=&quot;text&quot; :value=&quot;value&quot; @input=&quot;onInput&quot; v-on:keydown.enter=&quot;addUser&quot; ref=&quot;inp&quot; /&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">               &lt;/p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">               &lt;button @click=&quot;addUser&quot;&gt;新增用户&lt;/button&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                &lt;/div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              `</span>,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">//将输入的用户数据通知给父组件，来完成新增用户操作.</span></span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// this.$emit(&quot;add-user&quot;, this.userInfo);</span></span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.$emit(<span class="string">&quot;add-user&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="comment">// this.userInfo = &quot;&quot;;</span></span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">onInput</span>(<span class="params">e</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.$emit(<span class="string">&quot;input&quot;</span>, e.<span class="property">target</span>.<span class="property">value</span>);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">inp</span>.<span class="title function_">focus</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 用户列表</span></span></span><br><span class="line"><span class="language-javascript">      <span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;user-list&quot;</span>, &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="title function_">data</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">selectItem</span>: <span class="string">&quot;&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          &#125;;</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">props</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">type</span>: <span class="title class_">Array</span>,</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">default</span>: [],</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">template</span>: <span class="string">`</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">          &lt;div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  &lt;p v-if=&quot;users.length===0&quot;&gt;没有任何用户数据&lt;/p&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;ul v-else&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  &lt;li</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  v-for=&quot;(item,index) in users&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  :key=&quot;item.id&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  :style=&quot;&#123;backgroundColor:selectItem===item?&#x27;#dddddd&#x27;:&#x27;transparent&#x27;&#125;&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  @mousemove=&quot;selectItem=item&quot;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  &gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  编号：&#123;&#123;item.id&#125;&#125; 姓名:&#123;&#123;item.name&#125;&#125;---身高:&#123;&#123;item.height&#125;&#125;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">                  &lt;/li&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">              &lt;/ul&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">        &lt;/div&gt;</span></span></span><br><span class="line"><span class="string"><span class="language-javascript">          `</span>,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">el</span>: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">data</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">num</span>: <span class="number">100</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">totalCount</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: [],</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">height</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">userInfo</span>: <span class="string">&quot;abc&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">title</span>: <span class="string">&quot;用户管理&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">// isShow: false,</span></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">// showWarn: false, // 控制警告窗口的显示与隐藏</span></span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">        <span class="comment">//组件实例已创建时</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">async</span> <span class="title function_">created</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">const</span> users = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">getUserList</span>();</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">users</span> = users;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新用户身高</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="title function_">batchUpdate</span>();</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//关闭窗口</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">closeWindow</span>(<span class="params">data</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">isShow</span> = data;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">showWarn</span> = data;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//添加用户的信息</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">addUser</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">userInfo</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> &gt; <span class="number">0</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">push</span>(&#123;</span></span><br><span class="line"><span class="language-javascript">                  <span class="attr">id</span>: <span class="variable language_">this</span>.<span class="property">users</span>[<span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> - <span class="number">1</span>].<span class="property">id</span> + <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">                  <span class="attr">name</span>: <span class="variable language_">this</span>.<span class="property">userInfo</span>,</span></span><br><span class="line"><span class="language-javascript">                &#125;);</span></span><br><span class="line"><span class="language-javascript">                <span class="variable language_">this</span>.<span class="property">userInfo</span> = <span class="string">&quot;&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">                <span class="comment">//完成用户添加后，给出相应的提示信息</span></span></span><br><span class="line"><span class="language-javascript">                <span class="comment">// this.isShow = true;</span></span></span><br><span class="line"><span class="language-javascript">                <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">msgSuccess</span>.<span class="title function_">toggle</span>();</span></span><br><span class="line"><span class="language-javascript">              &#125;</span></span><br><span class="line"><span class="language-javascript">            &#125; <span class="keyword">else</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">// 显示错误警告信息</span></span></span><br><span class="line"><span class="language-javascript">              <span class="comment">// this.showWarn = true;</span></span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">msgWaring</span>.<span class="title function_">toggle</span>();</span></span><br><span class="line"><span class="language-javascript">            &#125;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="comment">//批量更新身高，动态的给users中添加身高属性</span></span></span><br><span class="line"><span class="language-javascript">          <span class="title function_">batchUpdate</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">this</span>.<span class="property">users</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">c</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   c.height = this.height;</span></span></span><br><span class="line"><span class="language-javascript">              <span class="comment">//   Vue.set(c, &quot;height&quot;, this.height);</span></span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.$set(c, <span class="string">&quot;height&quot;</span>, <span class="variable language_">this</span>.<span class="property">height</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getTotal</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;methods&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">users</span>.<span class="property">length</span> + <span class="string">&quot;个&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">getUserList</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve</span>) =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">                <span class="title function_">resolve</span>([</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;张三&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">2</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;李四&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                  &#123;</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">id</span>: <span class="number">3</span>,</span></span><br><span class="line"><span class="language-javascript">                    <span class="attr">name</span>: <span class="string">&quot;老王&quot;</span>,</span></span><br><span class="line"><span class="language-javascript">                  &#125;,</span></span><br><span class="line"><span class="language-javascript">                ]);</span></span><br><span class="line"><span class="language-javascript">              &#125;, <span class="number">2000</span>);</span></span><br><span class="line"><span class="language-javascript">            &#125;);</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">watch</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="attr">users</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">            <span class="attr">immediate</span>: <span class="literal">true</span>, <span class="comment">//立即执行</span></span></span><br><span class="line"><span class="language-javascript">            <span class="title function_">handler</span>(<span class="params">newValue, oldValue</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">              <span class="variable language_">this</span>.<span class="property">totalCount</span> = newValue.<span class="property">length</span> + <span class="string">&quot;个人&quot;</span>;</span></span><br><span class="line"><span class="language-javascript">            &#125;,</span></span><br><span class="line"><span class="language-javascript">          &#125;,</span></span><br><span class="line"><span class="language-javascript">        &#125;,</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>虚拟 DOM</strong></p>
<p><code>Vue</code>通过建立一个虚拟 DOM 来追踪自己要如何改变真实<code>DOM</code>.</p>
<p><strong><code>createElement</code>参数</strong></p>
<p>前面说过，<code>createElement</code>函数有三个参数。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title function_">createElement</span>(</span><br><span class="line">  <span class="comment">//&#123;string |Object|Function&#125;</span></span><br><span class="line">    <span class="comment">//第一个参数，可以是字符串，也可以是对象或者是函数</span></span><br><span class="line">    ‘div’</span><br><span class="line">    ,</span><br><span class="line">    <span class="comment">// 第二个参数是对象，表示的是一个与模板中属性对应的数据对象。该参数可选</span></span><br><span class="line">    &#123;</span><br><span class="line"></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">//第三个参数是一个数组,表示的是子节点数组</span></span><br><span class="line">    [</span><br><span class="line"></span><br><span class="line">    ]</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>下面，给<code>heading</code>组件添加第一个属性。</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 使用render函数创建的头部组件 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">heading</span> <span class="attr">level</span>=<span class="string">&quot;1&quot;</span> <span class="attr">:title</span>=<span class="string">&quot;title&quot;</span>&gt;</span> &#123;&#123;title&#125;&#125; <span class="tag">&lt;/<span class="name">heading</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们给<code>heading</code>组件动态添加了一个<code>title</code>属性。而我们知道<code>heading</code>组件，最终渲染成的是<code>h1</code>的元素，最终效果为：<code>&lt;h1 title=&#39;aaa&#39;&gt;</code>的形式。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// heading组件</span></span><br><span class="line"><span class="comment">//&lt;heading :level=&quot;1&quot;&gt;&#123;&#123;title&#125;&#125;&lt;/heading&gt; //这时要创建的组件</span></span><br><span class="line"><span class="comment">// &lt;h2 title=&quot;&quot;&gt;&lt;/h2&gt; //这时上面的组件最终渲染的结果</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;heading&quot;</span>, &#123;</span><br><span class="line">  <span class="attr">props</span>: &#123;</span><br><span class="line">    <span class="attr">level</span>: &#123;</span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">String</span>,</span><br><span class="line">      <span class="attr">required</span>: <span class="literal">true</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">title</span>: &#123;</span><br><span class="line">      <span class="attr">type</span>: <span class="title class_">String</span>,</span><br><span class="line">      <span class="attr">default</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="title function_">render</span>(<span class="params">h</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">h</span>(</span><br><span class="line">      <span class="string">&quot;h&quot;</span> + <span class="variable language_">this</span>.<span class="property">level</span>, <span class="comment">//参数1，表示要创建的元素</span></span><br><span class="line">      &#123; <span class="attr">attrs</span>: &#123; <span class="attr">title</span>: <span class="variable language_">this</span>.<span class="property">title</span> &#125; &#125;, <span class="comment">//参数2</span></span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">$slots</span>.<span class="property">default</span> <span class="comment">//参数3，子节点VNode数组。（这里没有使用参数2，&#123;&#123;tile&#125;&#125;就是一个子元素）</span></span><br><span class="line">    );</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>在上面的代码中，我们在<code>render</code>函数中给<code>h</code>函数添加了第二个参数，给最终生成的元素添加了<code>attrs</code>属性。</p>
<h2 id="20、函数式组件"><a href="#20、函数式组件" class="headerlink" title="20、函数式组件"></a>20、函数式组件</h2><p>组件没有管理任何状态，也没有监听任何传递给它的状态，也没有生命周期方法时，可以将组件标记为<code>functional</code>.这意味它无状态（没有响应式数据），也没有实例（没有<code>this</code>上下文）</p>
<p>因为只是函数，所以渲染的开销相对来说，较小。</p>
<p>函数化的组件中的 Render 函数，提供了第二个参数 context 作为上下文，data、props、slots、children 以及 parent 都可以通过 context 来访问。</p>
<p>这块内容简单了解一下就可以。</p>
<h2 id="21、混入"><a href="#21、混入" class="headerlink" title="21、混入"></a>21、混入</h2><p>混入(<code>mixin</code>)提供了一种非常灵活的方式，来分发<code>Vue</code>组件中的可复用功能，一个混入对象可以包含任意组件选项。当组件使用混入对象时，所有混入对象的选项被“混合”进入该组件本身的选项。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 定义一个混入对象</span></span><br><span class="line"><span class="keyword">var</span> myMixin = &#123;</span><br><span class="line">  <span class="attr">created</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">hello</span>();</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="attr">hello</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;hello world&quot;</span>);</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">component</span>(<span class="string">&quot;comp&quot;</span>, &#123;</span><br><span class="line">  <span class="attr">mixins</span>: [myMixin],</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>“混入”可以提高组件的复用功能，例如：上面所写的<code>hello</code>这个方法，不仅在一个组件中使用，还会</p>
<p>在其它组件中使用.那么，我们的处理方式就是，可以将<code>hello</code> 这个方法单独定义在一个地方，如果某个组件想要使用，可以直接将该方法注入到组件中。</p>
<h2 id="22、插件"><a href="#22、插件" class="headerlink" title="22、插件"></a>22、插件</h2><p>前面我们讲解的混入，组件封装等都可以提高组件的复用功能。</p>
<p>但是这种方式不适合分发，也就是不适合将这些内容上传到<code>github</code>上，<code>npm</code>上。而这种情况最适合通过<code>插件</code>来实现。</p>
<p>插件通常用来为<code>Vue</code>添加全局功能。插件的功能范围一般有下面几种：</p>
<ul>
<li>添加全局方法或者属性。例如：’element’</li>
<li>添加全局资源</li>
<li>通过全局混入来添加一些组件选项。例如<code>vue-router</code></li>
<li>添加<code>vue实例</code>方法，通过把它们添加到<code>Vue.prototype</code>上实现</li>
<li>一个库，提供自己的<code>API</code>，同时提供上面提到的一个或多个功能，例如<code>vue-router</code></li>
</ul>
<p><strong>插件声明</strong></p>
<p><code>Vue.js </code>的插件应该暴露一个 <code>install</code> 方法。这个方法的第一个参数是 <code>Vue</code> 构造器，第二个参数是一个可选的选项对象：</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="title class_">MyPlugin</span>.<span class="property">install</span> = <span class="keyword">function</span> (<span class="params">Vue, options</span>) &#123;</span><br><span class="line">  <span class="comment">// 1. 添加全局方法或 property</span></span><br><span class="line">  <span class="title class_">Vue</span>.<span class="property">myGlobalMethod</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// 逻辑...</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 2. 添加全局资源</span></span><br><span class="line">  <span class="title class_">Vue</span>.<span class="title function_">directive</span>(<span class="string">&#x27;my-directive&#x27;</span>, &#123;</span><br><span class="line">    bind (el, binding, vnode, oldVnode) &#123;</span><br><span class="line">      <span class="comment">// 逻辑...</span></span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">  &#125;)</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 3. 注入组件选项</span></span><br><span class="line">  <span class="title class_">Vue</span>.<span class="title function_">mixin</span>(&#123;</span><br><span class="line">    <span class="attr">created</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">      <span class="comment">// 逻辑...</span></span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">  &#125;)</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 4. 添加实例方法</span></span><br><span class="line">  <span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$myMethod</span> = <span class="keyword">function</span> (<span class="params">methodOptions</span>) &#123;</span><br><span class="line">    <span class="comment">// 逻辑...</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/luozhihao/p/7414419.html">https://www.cnblogs.com/luozhihao/p/7414419.html</a></p>
<h2 id="23、vue-cli使用"><a href="#23、vue-cli使用" class="headerlink" title="23、vue-cli使用"></a>23、<code>vue-cli</code>使用</h2><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">npm install -g @vue/cli</span><br></pre></td></tr></table></figure>

<p>通过使用<code>vue-clie</code>创建项目。</p>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="http://example.com">Justic</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="http://example.com/2022/07/13/Vue/Vue%E5%9F%BA%E7%A1%80/Vue%E5%9F%BA%E7%A1%80/">http://example.com/2022/07/13/Vue/Vue基础/Vue基础/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://justicc.top/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="http://example.com" target="_blank">Justic</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Vue/">Vue</a></div><div class="post_share"><div class="social-share" data-image="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/yj/wallhaven-yj1kgl.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer></script></div></div><div class="post-reward"><div class="reward-button"><i class="fas fa-qrcode"></i> 打赏</div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="/img/wechat.jpg" target="_blank"><img class="post-qr-code-img" src= "" data-lazy-src="/img/wechat.jpg" alt="微信"/></a><div class="post-qr-code-desc">微信</div></li><li class="reward-item"><a href="/img/alipay.jpg" target="_blank"><img class="post-qr-code-img" src= "" data-lazy-src="/img/alipay.jpg" alt="支付宝"/></a><div class="post-qr-code-desc">支付宝</div></li></ul></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2022/07/13/Vue/Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86/Vue%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86/"><img class="prev-cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/j3/wallhaven-j3qq15.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">Vue 响应式原理</div></div></a></div><div class="next-post pull-right"><a href="/2022/07/07/JavaScript/JavaScript%E5%BC%95%E6%93%8E/"><img class="next-cover" src= "" data-lazy-src="https://pic1.zhimg.com/v2-4dce785ff4595de55623611ab0055d33_1440w.jpg?source=172ae18b" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">JavaScript 引擎</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><div><a href="/2022/07/13/Vue/Vue%20Router/vueRouter/" title="Vue 路由"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/ne/wallhaven-ne8mzl.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-13</div><div class="title">Vue 路由</div></div></a></div><div><a href="/2022/07/13/Vue/Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86/Vue%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86/" title="Vue 响应式原理"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/j3/wallhaven-j3qq15.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-13</div><div class="title">Vue 响应式原理</div></div></a></div><div><a href="/2022/10/20/Vue/Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/Vue%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/" title="Vue 响应式解析"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/z8/wallhaven-z82evv.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-10-20</div><div class="title">Vue 响应式解析</div></div></a></div><div><a href="/2022/07/15/Vue/Vue%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%B8%B2%E6%9F%93/Vue%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%B8%B2%E6%9F%93/" title="Vue 服务器渲染"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/ne/wallhaven-ne8mzl.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-15</div><div class="title">Vue 服务器渲染</div></div></a></div><div><a href="/2022/07/15/Vue/Vue%20%E6%BA%90%E7%A0%81%E8%A7%A3%E8%AF%BB/Vue%E6%BA%90%E7%A0%81%E8%A7%A3%E8%AF%BB/" title="Vue 源码解读"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/j3/wallhaven-j3qq15.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-15</div><div class="title">Vue 源码解读</div></div></a></div><div><a href="/2022/07/15/Vue/Vue%20%E8%99%9A%E6%8B%9Fdom/Vue%20%E8%99%9A%E6%8B%9Fdom/" title="Vue 虚拟DOM"><img class="cover" src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/k7/wallhaven-k7jmg6.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-15</div><div class="title">Vue 虚拟DOM</div></div></a></div></div></div><hr/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div class="vcomment" id="vcomment"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src= "" data-lazy-src="https://portrait.gitee.com/uploads/avatars/user/2982/8948190_JIAXInT_1624177607.png!avatar200" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">Justic</div><div class="author-info__description">最是人间留不住 朱颜辞镜花辞树</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">22</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">2</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">3</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%80%E3%80%81Vue%E7%9F%A5%E8%AF%86%E7%82%B9%E4%B8%B2%E8%AE%B2"><span class="toc-text">一、Vue知识点串讲</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1%E3%80%81%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8"><span class="toc-text">1、基本使用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2%E3%80%81%E6%A8%A1%E6%9D%BF%E8%AF%AD%E6%B3%95"><span class="toc-text">2、模板语法</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#2-1-%E5%B1%9E%E6%80%A7%E7%BB%91%E5%AE%9A"><span class="toc-text">2.1 属性绑定</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3%E3%80%81-%E5%88%97%E8%A1%A8%E6%B8%B2%E6%9F%93"><span class="toc-text">3、 列表渲染</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4%E3%80%81v-model"><span class="toc-text">4、v-model</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5%E3%80%81v-on"><span class="toc-text">5、v-on</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6%E3%80%81Class-%E4%B8%8E-Style-%E7%BB%91%E5%AE%9A"><span class="toc-text">6、Class 与 Style 绑定</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7%E3%80%81%E6%9D%A1%E4%BB%B6%E6%B8%B2%E6%9F%93"><span class="toc-text">7、条件渲染</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8%E3%80%81%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7"><span class="toc-text">8、计算属性</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#9%E3%80%81%E4%BE%A6%E5%90%AC%E5%99%A8"><span class="toc-text">9、侦听器</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#10%E3%80%81%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E7%AE%80%E4%BB%8B"><span class="toc-text">10、生命周期简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#11%E3%80%81%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E6%8E%A2%E8%AE%A8"><span class="toc-text">11、生命周期探讨</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#12%E3%80%81%E7%BB%84%E4%BB%B6%E5%8C%96%E5%BA%94%E7%94%A8"><span class="toc-text">12、组件化应用</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#12-1-%E7%BB%84%E4%BB%B6%E6%A6%82%E8%BF%B0"><span class="toc-text">12.1 组件概述</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#12-2-%E7%BB%84%E4%BB%B6%E7%9A%84%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8"><span class="toc-text">12.2 组件的基本使用</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#12-3-%E5%B1%80%E9%83%A8%E7%BB%84%E4%BB%B6%E6%B3%A8%E5%86%8C"><span class="toc-text">12.3 局部组件注册</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#13%E3%80%81%E7%BB%84%E4%BB%B6%E9%80%9A%E4%BF%A1"><span class="toc-text">13、组件通信</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#13-1-%E7%88%B6%E7%BB%84%E4%BB%B6%E5%90%91%E5%AD%90%E7%BB%84%E4%BB%B6%E4%BC%A0%E5%80%BC"><span class="toc-text">13.1 父组件向子组件传值</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-2-%E5%AD%90%E7%BB%84%E4%BB%B6%E5%90%91%E7%88%B6%E7%BB%84%E4%BB%B6%E4%BC%A0%E5%80%BC"><span class="toc-text">13.2 子组件向父组件传值</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#13-3-%E5%85%84%E5%BC%9F%E7%BB%84%E4%BB%B6%E4%B9%8B%E9%97%B4%E6%95%B0%E6%8D%AE%E4%BC%A0%E9%80%92"><span class="toc-text">13.3 兄弟组件之间数据传递</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#14%E3%80%81%E7%BB%84%E4%BB%B6%E6%8F%92%E6%A7%BD%E5%BA%94%E7%94%A8"><span class="toc-text">14、组件插槽应用</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#14-1-%E6%8F%92%E6%A7%BD%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8"><span class="toc-text">14.1 插槽基本使用</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#14-2-%E5%85%B7%E5%90%8D%E6%8F%92%E6%A7%BD"><span class="toc-text">14.2 具名插槽</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#14-3-%E4%BD%9C%E7%94%A8%E5%9F%9F%E6%8F%92%E6%A7%BD"><span class="toc-text">14.3 作用域插槽</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#14-4-%E4%BD%9C%E7%94%A8%E5%9F%9F%E6%8F%92%E6%A7%BD%E6%A1%88%E4%BE%8B"><span class="toc-text">14.4. 作用域插槽案例</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#14-5-%E6%8F%92%E6%A7%BD%E5%BA%94%E7%94%A8%E6%80%BB%E7%BB%93"><span class="toc-text">14.5 插槽应用总结</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#15%E3%80%81Vue%E7%BB%84%E4%BB%B6%E5%8C%96%E7%9A%84%E7%90%86%E8%A7%A3"><span class="toc-text">15、Vue组件化的理解</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#16%E3%80%81%E5%B8%B8%E7%94%A8API%E8%AF%B4%E6%98%8E"><span class="toc-text">16、常用API说明</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#16-1-Vue-set"><span class="toc-text">16.1  Vue.set</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#16-2-Vue-delete"><span class="toc-text">16.2 Vue.delete</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#16-3-vm-on%E4%B8%8Evm-emit"><span class="toc-text">16.3 vm.$on与vm.$emit</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#16-3-1-%E5%88%97%E8%A1%A8%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1"><span class="toc-text">16.3.1 列表组件设计</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#16-3-2-%E7%94%A8%E6%88%B7%E6%B7%BB%E5%8A%A0%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1"><span class="toc-text">16.3.2 用户添加组件设计</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#16-3-3-%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6%E5%AE%9E%E7%8E%B0%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A"><span class="toc-text">16.3.3 自定义组件实现双向绑定</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#16-3-4-%E4%BD%BF%E7%94%A8%E6%8F%92%E6%A7%BD%E5%AE%8C%E6%88%90%E5%86%85%E5%AE%B9%E5%88%86%E5%8F%91"><span class="toc-text">16.3.4. 使用插槽完成内容分发</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#16-3-5-vm-on%E4%B8%8Evm-emit%E5%BA%94%E7%94%A8"><span class="toc-text">16.3.5 vm.$on与vm.$emit应用</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#16-4-vm-once%E4%B8%8Evm-off"><span class="toc-text">16.4 vm.$once与vm.$off</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#16-5-ref-%E5%92%8Cvm-refs"><span class="toc-text">16.5 ref 和vm.$refs</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#17%E3%80%81%E8%BF%87%E6%BB%A4%E5%99%A8"><span class="toc-text">17、过滤器</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#17-1-%E8%BF%87%E6%BB%A4%E5%99%A8%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8"><span class="toc-text">17.1 过滤器基本使用</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#17-2-%E5%B8%A6%E5%8F%82%E6%95%B0%E7%9A%84%E8%BF%87%E6%BB%A4%E5%99%A8"><span class="toc-text">17.2 带参数的过滤器</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#18%E3%80%81%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8C%87%E4%BB%A4"><span class="toc-text">18、自定义指令</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#18-1-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8C%87%E4%BB%A4%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95"><span class="toc-text">18.1 自定义指令基本用法</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#18-2-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8C%87%E4%BB%A4-%E5%B8%A6%E5%8F%82%E6%95%B0"><span class="toc-text">18.2 自定义指令-带参数</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#18-3-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B1%80%E9%83%A8%E6%8C%87%E4%BB%A4"><span class="toc-text">18.3 自定义局部指令</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#19%E3%80%81%E6%B8%B2%E6%9F%93%E5%87%BD%E6%95%B0"><span class="toc-text">19、渲染函数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#20%E3%80%81%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BB%84%E4%BB%B6"><span class="toc-text">20、函数式组件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#21%E3%80%81%E6%B7%B7%E5%85%A5"><span class="toc-text">21、混入</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#22%E3%80%81%E6%8F%92%E4%BB%B6"><span class="toc-text">22、插件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#23%E3%80%81vue-cli%E4%BD%BF%E7%94%A8"><span class="toc-text">23、vue-cli使用</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/2022/11/09/JavaScript/ES6%E6%96%B0%E7%89%B9%E6%80%A7/index/" title="ES6新特性"><img src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/m9/wallhaven-m9y289.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="ES6新特性"/></a><div class="content"><a class="title" href="/2022/11/09/JavaScript/ES6%E6%96%B0%E7%89%B9%E6%80%A7/index/" title="ES6新特性">ES6新特性</a><time datetime="2022-11-09T12:55:33.000Z" title="发表于 2022-11-09 20:55:33">2022-11-09</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/10/20/Vue/Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/Vue%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/" title="Vue 响应式解析"><img src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/z8/wallhaven-z82evv.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Vue 响应式解析"/></a><div class="content"><a class="title" href="/2022/10/20/Vue/Vue%20%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/Vue%E5%93%8D%E5%BA%94%E5%BC%8F%E8%A7%A3%E6%9E%90/" title="Vue 响应式解析">Vue 响应式解析</a><time datetime="2022-10-20T12:05:37.000Z" title="发表于 2022-10-20 20:05:37">2022-10-20</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/08/08/JavaScript/JavaScript%E5%8E%9F%E5%9E%8B%E5%92%8C%E5%8E%9F%E5%9E%8B%E9%93%BE/index/" title="JavaScript原型和原型链"><img src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/z8/wallhaven-z82evv.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="JavaScript原型和原型链"/></a><div class="content"><a class="title" href="/2022/08/08/JavaScript/JavaScript%E5%8E%9F%E5%9E%8B%E5%92%8C%E5%8E%9F%E5%9E%8B%E9%93%BE/index/" title="JavaScript原型和原型链">JavaScript原型和原型链</a><time datetime="2022-08-08T09:08:31.000Z" title="发表于 2022-08-08 17:08:31">2022-08-08</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/08/08/JavaScript/JavaScript%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%A2%9E%E5%BC%BA%E7%9F%A5%E8%AF%86/index/" title="JavaScript对象的增强知识"><img src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/j3/wallhaven-j3qq15.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="JavaScript对象的增强知识"/></a><div class="content"><a class="title" href="/2022/08/08/JavaScript/JavaScript%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%A2%9E%E5%BC%BA%E7%9F%A5%E8%AF%86/index/" title="JavaScript对象的增强知识">JavaScript对象的增强知识</a><time datetime="2022-08-08T07:43:36.000Z" title="发表于 2022-08-08 15:43:36">2022-08-08</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/08/08/JavaScript/JavaScript%E5%87%BD%E6%95%B0%E5%A2%9E%E5%BC%BA%E7%9F%A5%E8%AF%86/index/" title="JavaScript函数增强知识"><img src= "" data-lazy-src="https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/28/wallhaven-2881yx.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="JavaScript函数增强知识"/></a><div class="content"><a class="title" href="/2022/08/08/JavaScript/JavaScript%E5%87%BD%E6%95%B0%E5%A2%9E%E5%BC%BA%E7%9F%A5%E8%AF%86/index/" title="JavaScript函数增强知识">JavaScript函数增强知识</a><time datetime="2022-08-08T03:25:40.000Z" title="发表于 2022-08-08 11:25:40">2022-08-08</time></div></div></div></div></div></div></main><footer id="footer" style="background-image: url('https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/yj/wallhaven-yj1kgl.jpg')"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2023 By Justic</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a><img src= "" data-lazy-src="https://static.dy208.cn/o_1dfilp8ruo521thr1hvf18ji17soa.png">
<a href="http://www.beian.miit.gov.cn/"  style="color:#f72b07" target="_blank">晋ICP备2021014440号-2</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="chat_btn" type="button" title="聊天"><i class="fas fa-sms"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span>  数据库加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><hr/><div id="local-search-results"></div></div></div><div id="search-mask"></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.min.js"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="/js/search/local-search.js"></script><div class="js-pjax"><script>function loadValine () {
  function initValine () {
    const valine = new Valine(Object.assign({
      el: '#vcomment',
      appId: 'KgIigedIwh0GobYsWWfPMEdO-gzGzoHsz',
      appKey: 'WpJEQP22asTau19i2tq1yQhU',
      avatar: 'justic',
      serverURLs: '',
      emojiMaps: "",
      path: window.location.pathname,
      visitor: false
    }, null))
  }

  if (typeof Valine === 'function') initValine() 
  else getScript('https://cdn.jsdelivr.net/npm/valine/dist/Valine.min.js').then(initValine)
}

if ('Valine' === 'Valine' || !false) {
  if (false) btf.loadComment(document.getElementById('vcomment'),loadValine)
  else setTimeout(loadValine, 0)
} else {
  function loadOtherComment () {
    loadValine()
  }
}</script></div><div class="aplayer no-destroy" data-id="5076309057" data-server="netease" data-type="playlist" data-fixed="true" data-autoplay="true" data-lrcType="-1"> </div><script id="canvas_nest" defer="defer" color="0,0,255" opacity="0.7" zIndex="-1" count="99" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-nest.min.js"></script><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/activate-power-mode.min.js"></script><script>POWERMODE.colorful = true;
POWERMODE.shake = false;
POWERMODE.mobile = true;
document.body.addEventListener('input', POWERMODE);
</script><script id="click-show-text" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/click-show-text.min.js" data-mobile="true" data-text="富强,民主,文明,和谐,平等,公正,法治,爱国,敬业,诚信,友善" data-fontsize="15px" data-random="true" async="async"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/metingjs/dist/Meting.min.js"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><!-- hexo injector body_end start --><script data-pjax>
  function butterfly_clock_anzhiyu_injector_config(){
    var parent_div_git = document.getElementsByClassName('sticky_layout')[0];
    var item_html = '<div class="card-widget card-clock"><div class="card-glass"><div class="card-background"><div class="card-content"><div id="hexo_electric_clock"><img class="entered loading" id="card-clock-loading" src= "" data-lazy-src="https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu/lib/loading.gif" style="height: 120px; width: 100%;" data-ll-status="loading"/></div></div></div></div></div>';
    console.log('已挂载butterfly_clock_anzhiyu')
    parent_div_git.insertAdjacentHTML("afterbegin",item_html)
    }
  var elist = 'null'.split(',');
  var cpage = location.pathname;
  var epage = 'all';
  var qweather_key = 'f854dfdd82d747fca7fd04f092861e87';
  var gaud_map_key = '427416c518f4476a01117be40057a892';
  var baidu_ak_key = 'undefined';
  var flag = 0;
  var clock_rectangle = '112.982279,28.19409';
  var clock_default_rectangle_enable = 'false';

  for (var i=0;i<elist.length;i++){
    if (cpage.includes(elist[i])){
      flag++;
    }
  }

  if ((epage ==='all')&&(flag == 0)){
    butterfly_clock_anzhiyu_injector_config();
  }
  else if (epage === cpage){
    butterfly_clock_anzhiyu_injector_config();
  }
  </script><script src="https://widget.qweather.net/simple/static/js/he-simple-common.js?v=2.0"></script><script data-pjax src="https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu/lib/clock.min.js"></script><!-- hexo injector body_end end --></body></html>